pike.git / src / pike_types.cmod

version» Context lines:

pike.git/src/pike_types.cmod:162:    add_ref(res = mixed_type_string);    type_stack_mark();    return res;    }else{    return debug_pop_type();    }   }      PMOD_EXPORT char *get_name_of_type(TYPE_T t)   { -  switch(t) +  switch(t & 0xff)    {    case T_ARRAY: return "array";    case T_MAPPING: return "mapping";    case T_MULTISET: return "multiset";    case T_OBJECT: return "object";    case T_FUNCTION: return "function";    case T_PROGRAM: return "program";    case T_STRING: return "string";    case T_TYPE: return "type";    case T_INT: return "int";
pike.git/src/pike_types.cmod:256:    * FLOAT - -    * STRING len type ZERO, INT or OR len:8.1, Range:7.7    * TYPE type -    * PROGRAM type -    * MIXED - -    * VOID - -    * ZERO - -    * UNKNOWN - -    * INT min (int) max (int)    * OBJECT implements/is object id(int) +  * OPERATOR type Depends on bit #15. Added in 8.1    *    * Note that the cdr of a FUNCTION is a valid FUNCTION for the rest of    * the arguments.    *    * Note also that functions that don't take any arguments, or just    * a many argument just have a MANY node, and no FUNCTION node.    *    */   static struct block_allocator type_allocator = BA_INIT(sizeof(struct pike_type), 128);   
pike.git/src/pike_types.cmod:321:    t2 = &((*t2)->next);    }       car = t->car;    cdr = t->cdr;    type = t->type;       really_free_pike_type((struct pike_type*)debug_malloc_pass(t));       /* FIXME: Recursion: Should we use a stack? */ -  switch(type) { +  switch(type & 0xff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    case T_ARRAY:    case T_STRING:    /* Free car & cdr */
pike.git/src/pike_types.cmod:364:    debug_free_type_preamble (t);    goto loop;       case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    free_string((struct pike_string *)car);    t = (struct pike_type *) cdr;    debug_free_type_preamble (t);    goto loop;    +  case PIKE_T_OPERATOR: +  /* Free car and maybe cdr. */ +  if (type & 0x8000) { +  /* Free cdr. */ +  free_type(cdr); +  } +  t = car; +  debug_free_type_preamble(t); +  goto loop; +    #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':
pike.git/src/pike_types.cmod:416:       hash ^= (hash >> 20) ^ (hash >> 12);    hash ^= (hash >> 7) ^ (hash >> 4);       index = hash & pike_type_hash_size;   #ifdef PIKE_EXTRA_DEBUG    static unsigned INT32 extra_debug_index = (unsigned INT32)~0;   #endif /* PIKE_EXTRA_DEBUG */   #ifdef PIKE_DEBUG    /* PIKE_DEBUG code */ -  if (type & ~255) { +  if ((type & ~255) && ((type & 0xff) != PIKE_T_OPERATOR)) {    /* The bad type node on OSF/1 seems to be:    *    * type: 0xffff    * car: valid pointer.    * cdr: 0x400000000    * next: 0x100000000    */    Pike_fatal("Attempt to create an invalid type node: %d(%s)\n"    " car: %p\n"    " cdr: %p\n",
pike.git/src/pike_types.cmod:494:    " t->next:%p\n",    t->type, get_name_of_type(t->type),    t->car, car,    t->cdr, cdr,    t->next);    }   #endif /* PIKE_EXTRA_DEBUG */    if ((t->hash == hash) && (t->type == type) &&    (t->car == car) && (t->cdr == cdr)) {    /* Free car & cdr as appropriate. */ -  switch(type) { +  switch(type & 0xff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    case T_ARRAY:    case T_STRING:    /* Free car & cdr */
pike.git/src/pike_types.cmod:532:    case T_ASSIGN:    /* Free cdr */    free_type((struct pike_type *)debug_malloc_pass(cdr));    break;       case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    free_string((struct pike_string *)debug_malloc_pass(car));    free_type((struct pike_type *)debug_malloc_pass(cdr));    break; +  +  case PIKE_T_OPERATOR: +  if (type & 0x8000) { +  free_type((struct pike_type *)debug_malloc_pass(cdr)); +  } +  free_type((struct pike_type *)debug_malloc_pass(car)); +  break; +    #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':
pike.git/src/pike_types.cmod:599:    if (car && (flag_method & PT_COPY_CAR)) {    t->flags |= car->flags;    }    if (cdr && (flag_method & PT_COPY_CDR)) {    t->flags |= cdr->flags;    }    }    }      #ifdef DEBUG_MALLOC -  switch(type) { +  switch(type & 0xff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    case T_ARRAY:    case T_STRING:    debug_malloc_pass(car);
pike.git/src/pike_types.cmod:634:    case T_SCOPE:    debug_malloc_pass(cdr);    break;       case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    debug_malloc_pass(car);    debug_malloc_pass(cdr);    break;    +  case PIKE_T_OPERATOR: +  if (type & 0x8000) { +  debug_malloc_pass(cdr); +  } +  debug_malloc_pass(car); +  break; +     case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':    case '9':
pike.git/src/pike_types.cmod:835:   {    /* fprintf(stderr, "push_type_name(\"%s\")\n", name->str); */    add_ref(name);    *Pike_compiler->type_stackp = mk_type(PIKE_T_NAME,    (void *)name,    *Pike_compiler->type_stackp,    PT_COPY_CDR);    TYPE_STACK_DEBUG("push_type_name");   }    + static struct pike_type *apply_type_operator(enum PIKE_TYPE op, +  struct pike_type *arg1, +  struct pike_type *arg2); +  + void debug_push_type_operator(enum PIKE_TYPE op, struct pike_type *arg) + { +  struct pike_type *t = *Pike_compiler->type_stackp; +  int free_arg = 0; +  + #ifdef PIKE_DEBUG +  if ((op & 0xff) != 0x80) { +  Pike_fatal("Invalid operator for push_operator: 0x%04x\n", op); +  } + #endif +  if (op & 0x8000) { +  if (!arg) { +  Pike_compiler->type_stackp--; +  arg = *Pike_compiler->type_stackp; +  free_arg = 1; +  *Pike_compiler->type_stackp = t; +  } +  } +  +  /* Attempt to propagate the operator towards the leaf nodes. */ +  switch(t->type & 0xff) { +  case '0': case '1': case '2': case '3': case '4': +  case '5': case '6': case '7': case '8': case '9': +  case T_ASSIGN: +  case PIKE_T_OPERATOR: +  case PIKE_T_SCOPE: +  /* Deferred evaluation. */ +  if (op & 0x8000) { +  *Pike_compiler->type_stackp = mk_type(op, +  *Pike_compiler->type_stackp, +  arg, +  PT_COPY_BOTH); +  } else { +  *Pike_compiler->type_stackp = mk_type(op, +  *Pike_compiler->type_stackp, +  arg, +  PT_COPY_CAR); +  } +  break; +  case PIKE_T_NAME: +  case PIKE_T_ATTRIBUTE: +  { +  Pike_compiler->type_stackp--; +  push_finished_type(t->cdr); +  push_type_operator(op, arg); +  if (t->type == PIKE_T_NAME) { +  push_type_name((struct pike_string *)t->car); +  } else { +  push_type_attribute((struct pike_string *)t->car); +  } +  free_type(t); +  break; +  } +  case T_NOT: +  { +  /* Unary propagate. */ +  int unop = t->type; +  +  pop_type_stack(t->type); +  push_type_operator(op, arg); +  push_type(unop); +  break; +  } +  case T_AND: +  case T_OR: +  { +  struct pike_type *tmp; +  int binop = t->type; +  /* Propagate. */ +  pop_type_stack(t->type); +  tmp = *Pike_compiler->type_stackp; +  Pike_compiler->type_stackp--; +  push_type_operator(op, arg); +  Pike_compiler->type_stackp++; +  *Pike_compiler->type_stackp = tmp; +  push_type_operator(op, arg); +  push_type(binop); +  break; +  } +  default: +  *Pike_compiler->type_stackp = apply_type_operator(op, t, arg); +  free_type(t); +  break; +  } +  if (free_arg) { +  free_type(arg); +  } + } +    void debug_push_finished_type(struct pike_type *t)   {    copy_pike_type(*(++Pike_compiler->type_stackp), t);       TYPE_STACK_DEBUG("push_finished_type");   }      static void push_reverse_joiner_type(unsigned int type)   {    /* fprintf(stderr, "push_reverse_joiner_type(%d)\n", type); */    -  switch(type) { +  switch(type & 0xff) {    case T_OR:    case T_AND:    /* Special case: Check if the two top elements are equal. */    if (Pike_compiler->type_stackp[-1] == Pike_compiler->type_stackp[0]) {    free_type(*(Pike_compiler->type_stackp--));    return;    }    /* Make a new type of the top two types. */    --Pike_compiler->type_stackp;   #ifdef PIKE_DEBUG
pike.git/src/pike_types.cmod:879:   }      static void low_or_pike_types(struct pike_type *t1,    struct pike_type *t2,    int zero_implied);      void debug_push_type(unsigned int type)   {    /* fprintf(stderr, "push_type(%d)\n", type); */    -  switch(type) { +  switch(type & 0xff) {    case T_OR:    case T_AND:    /* Special case: Check if the two top elements are equal. */    if (Pike_compiler->type_stackp[-1] == Pike_compiler->type_stackp[0]) {    free_type(*(Pike_compiler->type_stackp--));    return;    }    if (Pike_compiler->type_stackp[0]->type == type) {    /* The top type is the same as our type.    * Split it and join the parts with the other type.
pike.git/src/pike_types.cmod:965:       case T_FLOAT:    case T_MIXED:    case T_VOID:    case T_ZERO:    case PIKE_T_UNKNOWN:    /* Leaf type. */    *(++Pike_compiler->type_stackp) = mk_type(type, NULL, NULL, 0);    break;    +  case PIKE_T_OPERATOR: +  push_type_operator(type, NULL); +  break; +     case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':    case '9':
pike.git/src/pike_types.cmod:1005:   #ifdef PIKE_DEBUG    if ((top->type != expected) &&    (top->type != PIKE_T_NAME) &&    (top->type != PIKE_T_ATTRIBUTE)) {    Pike_fatal("Unexpected type on stack: %d (expected %d)\n", top->type, expected);    }   #endif /* PIKE_DEBUG */    /* OPTIMIZE: It looks like this function is always called with    * expected == T_ARRAY.    */ -  switch(top->type) { +  switch(top->type & 0xff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    /* Both car & cdr. */    push_finished_type(top->cdr);    push_finished_type(top->car);
pike.git/src/pike_types.cmod:1057:    case '8':    case '9':    /* Leaf */    break;    case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    /* Pop the name and recurse. */    push_finished_type(top->cdr);    pop_type_stack(expected);    break; +  +  case PIKE_T_OPERATOR: +  if (top->type & 0x8000) { +  push_finished_type(top->cdr); +  } +  push_finished_type(top->car); +  break; +     default:    Pike_error("pop_type_stack(): Unhandled node type: %d\n", top->type);    }    free_type(top);       TYPE_STACK_DEBUG("pop_type_stack");   }      void debug_push_reverse_type(unsigned int type)   {    /* fprintf(stderr, "push_reverse_type(%d)\n", type); */    -  switch(type) { +  switch(type & 0x80ff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    case PIKE_T_ARRAY:    case PIKE_T_STRING: -  +  case PIKE_T_OPERATOR | 0x8000:    {    /* Binary type-node. -- swap the types. */    struct pike_type *tmp = Pike_compiler->type_stackp[0];    Pike_compiler->type_stackp[0] = Pike_compiler->type_stackp[-1];    Pike_compiler->type_stackp[-1] = tmp;    break;    }    }    push_type(type);       TYPE_STACK_DEBUG("push_reverse_type");   }      static int is_int_type(struct pike_type *t)   {    loop: -  switch(t->type) { +  switch(t->type & 0xff) {    case T_INT:    case T_ZERO:    case T_VOID:    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9': -  +  case PIKE_T_OPERATOR:    return 1;    case T_OR:    case T_AND:    return is_int_type(t->car) && is_int_type(t->cdr);    case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE:    case PIKE_T_SCOPE:    case T_ASSIGN:    t = t->cdr;    goto loop;
pike.git/src/pike_types.cmod:1244:    }    } else if (type->type == PIKE_T_NAME) {    /* Strip the name, since it won't be correct anymore. */    type = type->cdr;    goto recurse;    } else if (type->type == PIKE_T_ATTRIBUTE) {    /* Keep the attribute. */    push_finished_type_with_markers(type->cdr, markers, marker_set);    push_type_attribute((struct pike_string *)type->car);    goto done; +  } else if ((type->type & 0xff) == PIKE_T_OPERATOR) { +  push_finished_type_with_markers(type->car, markers, marker_set); +  push_type_operator(type->type, type->cdr); +  goto done;    }    /* FIXME: T_SCOPE */       if (type->car) {    /* Keep markers for assigns in the car. */    cdr_set = marker_set |    ((type->car->flags & PT_FLAG_ASSIGN)>>PT_ASSIGN_SHIFT);    } else {    cdr_set = marker_set;    }
pike.git/src/pike_types.cmod:2008:       case PIKE_T_UNKNOWN: fprintf(stderr, "unknown"); break;    case T_MANY: fprintf(stderr, "many"); break;    case T_OR: fprintf(stderr, "or"); break;    case T_AND: fprintf(stderr, "and"); break;    case T_NOT: fprintf(stderr, "not"); break;    case T_VOID: fprintf(stderr, "void"); break;    case T_ZERO: fprintf(stderr, "zero"); break;    case T_MIXED: fprintf(stderr, "mixed"); break;    +  case PIKE_T_OPERATOR: +  fprintf(stderr, "operator "); +  e++; +  switch(EXTRACT_UCHAR(a+e)<<8 | PIKE_T_OPERATOR) { +  default: +  fprintf(stderr, "unknown<0x%04x>", +  EXTRACT_UCHAR(a+e)<<8 | PIKE_T_OPERATOR); +  break; +  } +  break; +     default: fprintf(stderr, "%d",EXTRACT_UCHAR(a+e)); break;    }    }    fprintf(stderr, "\n");   }   #endif      void simple_describe_type(struct pike_type *s)   {    if (s) {    /* fprintf(stderr, "[[[%p]]]", s); */ -  switch(s->type) { +  switch(s->type & 0xff) {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    fprintf(stderr, "%d", s->type-'0');    break;       case PIKE_T_NAME:    fprintf(stderr, "{ %s = ", ((struct pike_string *)s->car)->str);    simple_describe_type(s->cdr);    fprintf(stderr, " }");    break;
pike.git/src/pike_types.cmod:2284:    case T_ZERO: fprintf(stderr, "zero"); break;    case T_MIXED: fprintf(stderr, "mixed"); break;    case PIKE_T_AUTO:    fprintf(stderr, "auto");    if (s->car && (s->car->type != T_ZERO)) {    fprintf(stderr, "(");    simple_describe_type(s->car);    fprintf(stderr, ")");    }    break; +  +  case PIKE_T_OPERATOR: +  fprintf(stderr, "operator<0x%04x>(", s->type); +  simple_describe_type(s->car); +  if (s->type & 0x8000) { +  fprintf(stderr, ","); +  simple_describe_type(s->cdr); +  } else { +  switch(s->type) {    default: -  +  if (s->cdr) { +  fprintf(stderr, ",0x%08lx)", CDR_TO_INT(s)); +  } else { +  fprintf(stderr, ")"); +  } +  break; +  } +  } +  break; +  +  default:    fprintf(stderr, "Unknown type node: %d, %p:%p",    s->type, s->car, s->cdr);   #ifdef DEBUG_MALLOC    debug_malloc_dump_references(s, 0, 2, 0);   #endif    break;    }    if (s->flags) {    fprintf(stderr, "[%06x]", s->flags);    }
pike.git/src/pike_types.cmod:2352:    goto loop;    default:    low_describe_type(s, t);    break;    }   }      void low_describe_type(struct string_builder *s, struct pike_type *t)   {    check_c_stack(1024); -  switch(t->type) +  switch(t->type) /* NB: No masking here! */    {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    string_builder_putchar(s, t->type);    break;       case T_ASSIGN:    string_builder_sprintf(s, "(%c=%T)", '0' + CAR_TO_INT(t), t->cdr);    break;   
pike.git/src/pike_types.cmod:2597:    break;    case PIKE_T_AUTO:    if (t->car->type != T_ZERO) {    string_builder_sprintf(s, "auto(%T)", t->car);    } else {    string_builder_strcat(s, "auto");    }    break;    default:    { +  if ((t->type & 0xff) == PIKE_T_OPERATOR) { +  string_builder_sprintf(s, "operator(0x%04x)(%T", t->type, t->car); +  if (t->type & 0x8000) { +  string_builder_sprintf(s, ",%T)", t->cdr); +  } else if (t->cdr) { +  string_builder_sprintf(s, ",0x%08lx)", CDR_TO_INT(t)); +  } else { +  string_builder_strcat(s, ")"); +  } +  } else {    string_builder_sprintf(s, "unknown code(%d)", t->type); -  +  }    break;    }    }   }      struct pike_string *describe_type(struct pike_type *type)   {    struct string_builder s;    ONERROR err;    if(!type) return make_shared_string("mixed");
pike.git/src/pike_types.cmod:2620:    low_describe_type(&s, type);    UNSET_ONERROR(err);    return finish_string_builder(&s);   }         /******/      TYPE_T compile_type_to_runtime_type(struct pike_type *t)   { -  switch(t->type) +  switch(t->type) /* Note: No masking here. */    {    case PIKE_T_RING:    return compile_type_to_runtime_type(t->car);       case T_OR:    {    TYPE_T tmp = compile_type_to_runtime_type(t->car);    if(tmp == compile_type_to_runtime_type(t->cdr))    return tmp;    }
pike.git/src/pike_types.cmod:2678:    *    * @param t    * Type to check.    */   int deprecated_typep(struct pike_type *t)   {    struct pike_string *deprecated_string;    MAKE_CONST_STRING(deprecated_string, "deprecated");       while (t) { -  switch(t->type) { +  switch(t->type & 0xff) {    case PIKE_T_ATTRIBUTE:    if (((struct pike_string*)t->car) == deprecated_string) {    return 1;    }    /* FALLTHRU */    case PIKE_T_SCOPE:    case T_ASSIGN:    case PIKE_T_NAME:    t = t->cdr;    continue; -  +  case PIKE_T_OPERATOR: +  t = t->car; +  continue;    }    break;    }    return 0;   }      int get_int_type_range(struct pike_type *t, INT_TYPE *range)   {    int ret = 0;    loop:
pike.git/src/pike_types.cmod:3454:   #endif   {    int correct_args;    struct pike_type *ret;    if(a == b) return a;      #ifdef PIKE_DEBUG    fatal_check_c_stack(1024);   #endif    -  switch(a->type) +  switch(a->type & 0xff)    {    case T_AND:    ret = low_match_types(a->car, b, flags);    if(!ret) return 0;    return low_match_types(a->cdr, b, flags);       case T_OR:    ret = low_match_types(a->car, b, flags);    if(ret && !(flags & NO_SHORTCUTS)) return ret;    if(ret)
pike.git/src/pike_types.cmod:3554:    free_type(tmp);    free_type(t);    } else {    a_markers[m] = t;    }    return res;    }    else    return low_match_types(mixed_type_string, b, flags);    } +  +  case PIKE_T_OPERATOR: +  { +  struct pike_type *t = apply_type_operator(a->type, a->car, a->cdr); +  ret = low_match_types(t, b, flags); +  free_type(t); +  return ret;    } -  +  }    -  switch(b->type) +  switch(b->type & 0xff)    {    case T_AND:    ret = low_match_types(a, b->car, flags);    if(!ret) return 0;    return low_match_types(a, b->cdr, flags);       case T_OR:    ret = low_match_types(a, b->car, flags);    if(ret && !(flags & NO_SHORTCUTS)) return ret;    if(ret)
pike.git/src/pike_types.cmod:3646:    free_type(tmp);    free_type(t);    } else {    b_markers[m] = t;    }    return res;    }    else    return low_match_types(a, mixed_type_string, flags);    } +  +  case PIKE_T_OPERATOR: +  { +  struct pike_type *t = apply_type_operator(b->type, b->car, b->cdr); +  ret = low_match_types(a, t, flags); +  free_type(t); +  return ret;    } -  +  }       /* 'mixed' matches anything */       if((a->type == T_ZERO || a->type == T_MIXED) &&    !(flags & (A_EXACT|B_EXACT)) &&    (b->type != T_VOID))    {   #if 1    switch(b->type)    {
pike.git/src/pike_types.cmod:4009:   #endif /* 0 */       if(a == b) return 1;      #ifdef TYPE_GROUPING    if (a->type != T_OR) {    flags &= ~LE_A_GROUPED;    }   #endif    -  switch(a->type) +  switch(a->type & 0xff)    {    case T_AND:    /* OK if either of the parts is a subset. */    /* FIXME: What if b also contains an AND? */    ret = low_pike_types_le(a->car, b, array_cnt, flags);    if(!ret) {    a = a->cdr;    goto recurse;    }    if ((a->flags | b->flags) & PT_FLAG_ASSIGN) {
pike.git/src/pike_types.cmod:4214:    }    } else {    if(a_markers[m]) {    a = a_markers[m];    } else {    a = mixed_type_string;    }    }    goto recurse;    } +  +  case PIKE_T_OPERATOR: +  { +  struct pike_type *t = apply_type_operator(a->type, a->car, a->cdr); +  ret = low_pike_types_le(t, b, array_cnt, flags); +  free_type(t); +  return ret;    } -  +  }      #ifdef TYPE_GROUPING    if (b->type != T_OR) {    flags &= ~LE_B_GROUPED;    }   #endif    -  switch(b->type) +  switch(b->type & 0xff)    {    case T_AND:    /* OK, if a is a subset of both parts. */    ret = low_pike_types_le(a, b->car, array_cnt, flags);    if(!ret) return 0;    b = b->cdr;    goto recurse;       case T_OR:    /* OK if a is a subset of either of the parts,
pike.git/src/pike_types.cmod:4377:    }    } else {    if(b_markers[m]) {    b = b_markers[m];    } else {    b = mixed_type_string;    }    }    goto recurse;    } +  +  case PIKE_T_OPERATOR: +  { +  struct pike_type *t = apply_type_operator(b->type, b->car, b->cdr); +  ret = low_pike_types_le(a, t, array_cnt, flags); +  free_type(t); +  return ret;    } -  +  }       if ((array_cnt < 0) && (b->type == T_ARRAY)) {    while (b->type == T_ARRAY) {    b = b->cdr;    if (!++array_cnt) break;    }    goto recurse;    } else if ((array_cnt > 0) && (a->type == T_ARRAY)) {    while (a->type == T_ARRAY) {    a = a->cdr;
pike.git/src/pike_types.cmod:4802:   }      /*    * Return the return type from a function call.    */   static int low_get_return_type(struct pike_type *a, struct pike_type *b)   {    struct compilation *c = THIS_COMPILATION;    int tmp;    CHECK_COMPILER(); -  switch(a->type) +  switch(a->type & 0xff)    {    case T_OR:    {    struct pike_type *o1, *o2;    o1=o2=0;       type_stack_mark();    if(low_get_return_type(a->car, b))    {    o1=pop_unfinished_type();
pike.git/src/pike_types.cmod:4857:    push_type_attribute((struct pike_string *)a->car);    return 1;    }    return 0;       case T_ARRAY:    tmp = low_get_return_type(a->cdr, b);    if(!tmp) return 0;    push_unlimited_array_type(T_ARRAY);    return 1; +  +  case PIKE_T_OPERATOR: +  { +  struct pike_type *t = apply_type_operator(a->type, a->car, a->cdr); +  tmp = low_get_return_type(t, b); +  free_type(t); +  return tmp;    } -  +  }       a = low_match_types(a, b, NO_SHORTCUTS);    if(a)    {   #if 0    if ((c->lex.pragmas & ID_STRICT_TYPES) &&    !low_pike_types_le(a, b, 0, 0)) {    yyreport_type(REPORT_WARNING, NULL, 0, b, NULL, 0, a, 0, "Type mismatch");    }   #endif /* 0 */ -  switch(a->type) +  switch(a->type & 0xff)    {    case T_FUNCTION:    a = a->cdr;    while(a->type == T_FUNCTION) {    a = a->cdr;    }    if (a->type != T_MANY) {    return low_get_return_type(a, mixed_type_string);    }    /* FALLTHRU */
pike.git/src/pike_types.cmod:5611:    struct pike_type *index_type,    node *n)   {    return low_check_indexing(type, index_type, n);   }      static int low_count_arguments(struct pike_type *q)   {    int num=0, num2;    -  switch(q->type) +  switch(q->type & 0xff)    {    case T_OR:    num = low_count_arguments(q->car);    num2 = low_count_arguments(q->cdr);    if(num<0 && num2>0) return num;    if(num2<0 && num>0) return num2;    if(num2<0 && num<0) return ~num>~num2?num:num2;    return num>num2?num:num2;       case T_AND:
pike.git/src/pike_types.cmod:5637:    return num<num2?num:num2;       case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE:    case T_ASSIGN:    case T_SCOPE:    return low_count_arguments(q->cdr);       default: return MAX_INT32;    +  case PIKE_T_OPERATOR: +  { +  struct pike_type *t = apply_type_operator(q->type, q->car, q->cdr); +  num = low_count_arguments(t); +  free_type(t); +  return num; +  } +     case T_FUNCTION:    while(q->type == T_FUNCTION)    {    num++;    q = q->cdr;    }       if (q->type != T_MANY) {    num2 = low_count_arguments(q);    if (num2 == MAX_INT32) return num2;
pike.git/src/pike_types.cmod:5769:      /* Get the type for the specified argument in a function type.    * Argument number -1 is the return type.    * True arguments are counted from zero.    */   struct pike_type *get_argument_type(struct pike_type *fun, int arg_no)   {    struct pike_type *tmp, *tmp2;       loop: -  switch(fun->type) { +  switch(fun->type & 0xff) {    case T_OR:    fun = or_pike_types(tmp = get_argument_type(fun->car, arg_no),    tmp2 = get_argument_type(fun->cdr, arg_no),    1);    free_type(tmp);    free_type(tmp2);    return fun;    -  +  case PIKE_T_OPERATOR: +  tmp = apply_type_operator(fun->type, fun->car, fun->cdr); +  tmp2 = get_argument_type(tmp, arg_no); +  free_type(tmp); +  return tmp2; +     case T_FUNCTION:    if (arg_no > 0) {    arg_no--;    fun = fun->cdr;    goto loop;    }    /* FALLTHRU */    case T_MANY:    if (arg_no < 0) {    add_ref(fun->cdr);
pike.git/src/pike_types.cmod:6710:    }   #endif /* PIKE_DEBUG */       loop:    /* Count the number of array levels. */    while(fun_type->type == PIKE_T_ARRAY) {    array_cnt++;    fun_type = fun_type->cdr;    }    -  switch(fun_type->type) { +  switch(fun_type->type & 0xff) {    case T_SCOPE:    /* FIXME: Save and restore the corresponding marker set. */    case T_ASSIGN:    case PIKE_T_NAME:    fun_type = fun_type->cdr;    goto loop;       case PIKE_T_ATTRIBUTE:    res = lower_new_check_call(fun_type->cdr, arg_type, flags, sval CHECK_CALL_ARGS);    if (!res) return NULL;
pike.git/src/pike_types.cmod:6885:    * Untyped object. mixed    * Failed to lookup program id. mixed    * Program does not have the lfun `()(). NULL    */       /* FALLTHRU */    case PIKE_T_MIXED:    copy_pike_type(res, mixed_type_string);    break;    +  case PIKE_T_OPERATOR: +  tmp = apply_type_operator(fun_type->type, fun_type->car, fun_type->cdr); +  res = lower_new_check_call(tmp, arg_type, flags, sval CHECK_CALL_ARGS); +  free_type(tmp); +  break; +     case PIKE_T_FUNCTION:    case T_MANY:    /* Special case to detect workarounds for the old    * function call checker.    */    tmp = NULL;    if (((arg_type->type != T_NOT) ||    (arg_type->car->type != T_MIXED)) &&    (fun_type->car->type == T_NOT) &&    (fun_type->car->car->type == T_OR) &&
pike.git/src/pike_types.cmod:7229:    }   #endif /* PIKE_DEBUG */       loop:    /* Count the number of array levels. */    while(fun_type->type == PIKE_T_ARRAY) {    array_cnt++;    fun_type = fun_type->cdr;    }    -  switch(fun_type->type) { +  switch(fun_type->type & 0xff) {    case PIKE_T_SCOPE:    case T_ASSIGN:    case PIKE_T_NAME:    fun_type = fun_type->cdr;    goto loop;       case PIKE_T_ATTRIBUTE:    tmp = new_get_return_type(fun_type->cdr, flags);    if (!tmp) break;    if (c) {
pike.git/src/pike_types.cmod:7365:    } while(fun_type->type == PIKE_T_FUNCTION);    if (fun_type->type != T_MANY) {    /* Still too few arguments. */    break;    }    /* FALLTHRU */    case T_MANY:    copy_pike_type(res, fun_type->cdr);    break;    +  case PIKE_T_OPERATOR: +  tmp = apply_type_operator(fun_type->type, fun_type->car, fun_type->cdr); +  res = new_get_return_type(tmp, flags); +  free_type(tmp); +  break; +     default:    /* Not a callable. */    break;    }       if (!res) {   #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "Failed.\n");    }
pike.git/src/pike_types.cmod:7539:    }      #ifdef PIKE_DEBUG    if (l_flag > 2) {    fprintf(stderr, "get_first_arg_type(");    simple_describe_type(fun_type);    fprintf(stderr, ", 0x%04x)\n", flags);    }   #endif    -  switch(fun_type->type) { +  switch(fun_type->type & 0xff) {    case PIKE_T_SCOPE:    case T_ASSIGN:    case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE:    case PIKE_T_RING:    fun_type = fun_type->cdr;    goto loop;    -  +  case PIKE_T_OPERATOR: +  tmp = apply_type_operator(fun_type->type, fun_type->car, fun_type->cdr); +  res = get_first_arg_type(tmp, flags); +  free_type(tmp); +  break; +     case T_OR:    if (!(res = get_first_arg_type(fun_type->car, flags))) {    fun_type = fun_type->cdr;    goto loop;    }    if (!(tmp = get_first_arg_type(fun_type->cdr, flags))) {    break;    }    res = or_pike_types(tmp2 = res, tmp, 1);    free_type(tmp);
pike.git/src/pike_types.cmod:7972:    } while(args);    }       return fun_type;   }      struct pike_type *zzap_function_return(struct pike_type *a,    struct pike_type *fun_ret)   {    struct pike_type *ret = NULL; -  switch(a->type) +  switch(a->type & 0xff)    {    case T_SCOPE:    ret = zzap_function_return(a->cdr, fun_ret);    if (!ret) return NULL;    type_stack_mark();    push_finished_type(ret);    free_type(ret);    push_scope_type(CAR_TO_INT(a));    return pop_unfinished_type();   
pike.git/src/pike_types.cmod:8044:    case T_MIXED:    /* I wonder when this occurrs, but apparently it does... */    /* FIXME: */    type_stack_mark();    push_finished_type(fun_ret);    push_type(T_VOID);    push_type(T_MIXED);    push_type(T_OR);    push_type(T_MANY);    return pop_unfinished_type(); +  +  case PIKE_T_OPERATOR: +  { +  struct pike_type *tmp = apply_type_operator(a->type, a->car, a->cdr); +  ret = zzap_function_return(tmp, fun_ret); +  free_type(tmp); +  return ret;    } -  +  }   /* This error is bogus /Hubbe    Pike_fatal("zzap_function_return() called with unexpected value: %d\n",    EXTRACT_UCHAR(a));   */    return NULL;   }    -  + struct pike_type *apply_type_operator(enum PIKE_TYPE op, +  struct pike_type *arg1, +  struct pike_type *arg2) + { +  struct pike_type *res = NULL; +  switch(op) { +  default: +  Pike_fatal("apply_type_operator(): Unknown operator: 0x%04x\n", op); +  break; +  } +  if (!res) { +  res = mixed_type_string; +  add_ref(res); +  } +  return res; + } +    struct pike_type *get_lax_type_of_svalue( const struct svalue *c )   {    struct pike_type *res;    if (TYPEOF(*c) == T_INT)    {    if (c->u.integer)    copy_pike_type(res, int_type_string);    else    copy_pike_type(res, zero_type_string);    }
pike.git/src/pike_types.cmod:8696:    }    low_make_pike_type(type_string + 2 + bytes + (1<<size_shift), cont);    if (type_string[0] == PIKE_T_NAME) {    push_type_name(str = end_shared_string(str));    } else {    push_type_attribute(str = end_shared_string(str));    }    free_string(str);    break;    } +  +  case PIKE_T_OPERATOR: +  { +  type |= type_string[1]<<8; +  if (type & 0x8000) { +  low_make_pike_type(type_string + 2, cont); +  low_make_pike_type(*cont, cont); +  push_reverse_type(type); +  } else { +  switch(type) { +  default: +  Pike_fatal("compile_type_string(): Unknown operator: 0x%04x\n", type); +  break; +  } +  } +  break; +  }   #ifdef PIKE_DEBUG    default:    Pike_fatal("compile_type_string(): Error in type string %d.\n", type);    UNREACHABLE(break);   #endif    }   }      void type_stack_mark(void)   {
pike.git/src/pike_types.cmod:8738:    return pop_unfinished_type();   }      int pike_type_allow_premature_toss(struct pike_type *type)   {    again:   #if 0    fprintf(stderr, "pike_type_allow_premature_toss(): Type: %d\n",    type->type);   #endif /* 0 */ -  switch(type->type) +  switch(type->type & 0xff)    {    default:   #ifdef PIKE_DEBUG    Pike_fatal("pike_type_allow_premature_toss: Unknown type (code: %d)\n",    type->type);    UNREACHABLE(return 0);   #endif    case T_NOT:    return !pike_type_allow_premature_toss(type->car);       case T_OBJECT:    case T_MIXED:    case T_FUNCTION:    case T_MANY: -  +  case PIKE_T_OPERATOR:    return 0;       case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE:    case T_SCOPE:    case T_ASSIGN:    case T_ARRAY:    type = type->cdr;    goto again;   
pike.git/src/pike_types.cmod:8795:    case T_FLOAT:    case T_STRING:    case PIKE_T_ZERO:    case T_VOID:    return 1;    }   }      static void low_type_to_string(struct byte_buffer *buf, struct pike_type *t)   { +  /* FIXME: PIKE_T_OPERATOR */ +     recurse:    switch(t->type) {    case T_MULTISET:    case T_TYPE:    case T_PROGRAM:    buffer_add_char(buf, t->type ^ MIN_REF_TYPE);    t = t->car;    goto recurse;       case T_ARRAY:
pike.git/src/pike_types.cmod:9155:      PMOD_EXPORT void *find_type(struct pike_type *t,    void *(*cb)(struct pike_type *))   {    void *res;    if (!t) return NULL;       res = cb(t);    if (res) return res;    -  switch(t->type) { +  switch(t->type & 0xff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    res = find_type(t->car, cb);    if (res) return res;    /* FALLTHRU */
pike.git/src/pike_types.cmod:9180:    case T_ARRAY:    case T_STRING:    return find_type(t->cdr, cb);       case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    return find_type(t->car, cb);    +  case PIKE_T_OPERATOR: +  if (t->type & 0x8000) { +  res = find_type(t->cdr, cb); +  if (res) return res; +  } +  return find_type(t->car, cb); +    #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':
pike.git/src/pike_types.cmod:9226:    break;   #endif    case VISIT_COMPLEX_ONLY:    visit_leave(t, PIKE_T_TYPE, extra);    return;    case VISIT_COUNT_BYTES:    mc_counted_bytes += sizeof (struct pike_type);    break;    }    -  switch (t->type) { +  switch (t->type & 0xff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    case T_ARRAY:    case T_STRING:    if (t->car) {
pike.git/src/pike_types.cmod:9256:    case T_TYPE:    case T_PROGRAM:    visit_type_ref (t->car, REF_TYPE_INTERNAL, extra);    break;    case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    visit_string_ref ((struct pike_string *) t->car, REF_TYPE_INTERNAL,    extra);    visit_type_ref (t->cdr, REF_TYPE_INTERNAL, extra);    break; +  +  case PIKE_T_OPERATOR: +  if (t->type & 0x8000) { +  visit_type_ref(t->cdr, REF_TYPE_INTERNAL, extra); +  } +  visit_type_ref(t->car, REF_TYPE_INTERNAL, extra); +  break; +    #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':
pike.git/src/pike_types.cmod:9294:      /* This is only enough gc stuff to detect leaking pike_type structs    * and to locate references to them. More is needed if types are    * extended to contain pointers to other memory objects or if they    * might contain cycles. */      void gc_mark_type_as_referenced(struct pike_type *t)   {    if (gc_mark(t, PIKE_T_TYPE)) {    GC_ENTER(t, PIKE_T_TYPE) { -  switch(t->type) { +  switch(t->type & 0xff) {    case PIKE_T_SCOPE:    case T_ASSIGN:    case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE:    if (t->cdr) gc_mark_type_as_referenced(t->cdr);    break;    case PIKE_T_FUNCTION:    case T_MANY:    case PIKE_T_RING:    case PIKE_T_TUPLE:
pike.git/src/pike_types.cmod:9318:    case PIKE_T_ARRAY:    case PIKE_T_STRING:    if (t->cdr) gc_mark_type_as_referenced(t->cdr);    /* FALLTHROUGH */    case PIKE_T_MULTISET:    case T_NOT:    case PIKE_T_TYPE:    case PIKE_T_PROGRAM:    if (t->car) gc_mark_type_as_referenced(t->car);    break; +  case PIKE_T_OPERATOR: +  if (t->type & 0x8000) { +  gc_mark_type_as_referenced(t->cdr);    } -  +  gc_mark_type_as_referenced(t->car); +  break; +  }    } GC_LEAVE;    }   }      #ifdef PIKE_DEBUG   static void gc_mark_external_types(struct callback *UNUSED(cb),    void *UNUSED(a), void *UNUSED(b))   {    unsigned int e;    for (e = 0; e < NELEM (a_markers); e++) {
pike.git/src/pike_types.cmod:9389:    }   #endif   }   #endif      void gc_check_type (struct pike_type *t)   {    debug_malloc_touch (t);       GC_ENTER (t, T_TYPE) { -  switch (t->type) { +  switch (t->type & 0xff) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    case T_ARRAY:    case T_STRING:    if (t->car) {
pike.git/src/pike_types.cmod:9424:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case PIKE_T_AUTO:    debug_gc_check (t->car, " as car in a type");    break;    case T_SCOPE:    case T_ASSIGN:    debug_gc_check (t->cdr, " as cdr in a type");    break; +  case PIKE_T_OPERATOR: +  if (t->type & 0x8000) { +  debug_gc_check (t->cdr, " as cdr in a type"); +  } +  debug_gc_check (t->car, " as car in a type"); +  break;   #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':