pike.git / src / pike_types.cmod

version» Context lines:

pike.git/src/pike_types.cmod:261:    * 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    * FIND_LFUN object type lfun (int) Added in 8.1 +  * TRANSITIVE fun_type fun_type 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.    * -  +  * TRANSITIVE has a car with the current state, and a cdr with the +  * function type to apply. +  *    */   static struct block_allocator type_allocator = BA_INIT(sizeof(struct pike_type), 128);      PMOD_EXPORT void really_free_pike_type(struct pike_type * t) {    ba_free(&type_allocator, t);   }      ATTRIBUTE((malloc))   PMOD_EXPORT struct pike_type * alloc_pike_type(void) {    struct pike_type *t = ba_alloc(&type_allocator);
pike.git/src/pike_types.cmod:336:    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: +  case PIKE_T_TRANSITIVE:    /* Free car & cdr */    free_type(car);    t = (struct pike_type *) cdr;    debug_free_type_preamble (t);    goto loop;       case PIKE_T_AUTO:    if (!car)    break;    /* FALLTHRU */
pike.git/src/pike_types.cmod:519:    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: +  case PIKE_T_TRANSITIVE:    /* Free car & cdr */    free_type((struct pike_type *)debug_malloc_pass(car));    free_type((struct pike_type *)debug_malloc_pass(cdr));    break;       case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    /* Free car */
pike.git/src/pike_types.cmod:632:    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: +  case PIKE_T_TRANSITIVE:    debug_malloc_pass(car);    debug_malloc_pass(cdr);    break;       case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case PIKE_T_AUTO:    debug_malloc_pass(car);
pike.git/src/pike_types.cmod:1038:    return;    }    /* FALLTHRU */    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:    /* Make a new type of the top two types. */    --Pike_compiler->type_stackp;    *Pike_compiler->type_stackp = mk_type(type,    *(Pike_compiler->type_stackp+1),    *Pike_compiler->type_stackp,    PT_COPY_BOTH);    break;       case T_PROGRAM:    if ((*Pike_compiler->type_stackp)->type != T_OBJECT) {
pike.git/src/pike_types.cmod:1140:    * expected == T_ARRAY.    */    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: +  case PIKE_T_TRANSITIVE:    /* Both car & cdr. */    push_finished_type(top->cdr);    push_finished_type(top->car);    break;    case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case PIKE_T_AUTO:    /* car */
pike.git/src/pike_types.cmod:1215:    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: +  case PIKE_T_TRANSITIVE:    {    /* 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);   
pike.git/src/pike_types.cmod:1385:    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; +  } else if (type->type == PIKE_T_TRANSITIVE) { +  push_finished_type(type->cdr); +  push_finished_type_with_markers(type->car, markers, marker_set); +  push_type(PIKE_T_TRANSITIVE); +  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:2161:    e++;    switch(EXTRACT_UCHAR(a+e)<<8 | PIKE_T_OPERATOR) {    case PIKE_T_FIND_LFUN: fprintf(stderr, "find_lfun"); break;    default:    fprintf(stderr, "unknown<0x%04x>",    EXTRACT_UCHAR(a+e)<<8 | PIKE_T_OPERATOR);    break;    }    break;    +  case PIKE_T_TRANSITIVE: +  fprintf(stderr, "transitive"); +  break; +     default: fprintf(stderr, "%d",EXTRACT_UCHAR(a+e)); break;    }    }    fprintf(stderr, "\n");   }   #endif      void simple_describe_type(struct pike_type *s)   {    if (s) {
pike.git/src/pike_types.cmod:2460:    if (s->cdr) {    fprintf(stderr, ",0x%08lx)", CDR_TO_INT(s));    } else {    fprintf(stderr, ")");    }    break;    }    }    break;    +  case PIKE_T_TRANSITIVE: +  fprintf(stderr, "transitive("); +  simple_describe_type(s->car); +  fprintf(stderr, ", "); +  simple_describe_type(s->cdr); +  fprintf(stderr, ")"); +  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:2777:    } else {    string_builder_strcat(s, "auto");    }    break;       case PIKE_T_FIND_LFUN:    string_builder_sprintf(s, "find_lfun(%T, \"%S\")",    t->car, lfun_strings[CDR_TO_INT(t)]);    break;    +  case PIKE_T_TRANSITIVE: +  string_builder_sprintf(s, "transitive(%T, %T)", t->car, t->cdr); +  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, ")");
pike.git/src/pike_types.cmod:2884:    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: +  case PIKE_T_TRANSITIVE:    t = t->car;    continue;    }    break;    }    return 0;   }      int get_int_type_range(struct pike_type *t, INT_TYPE *range)   {
pike.git/src/pike_types.cmod:3862:    struct pike_type *t = a->car;    if ((t->type >= '0') && (t->type <= '9')) {    t = a_markers[t->type - '0'];    if (!t) t = zero_type_string;    }    t = apply_type_operator(a->type, t, a->cdr);    ret = low_match_types(t, b, flags);    free_type(t);    return ret;    } +  +  case PIKE_T_TRANSITIVE: +  { +  /* FIXME */ +  return a;    } -  +  }       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);
pike.git/src/pike_types.cmod:3967:    struct pike_type *t = b->car;    if ((t->type >= '0') && (t->type <= '9')) {    t = b_markers[t->type - '0'];    if (!t) t = zero_type_string;    }    t = apply_type_operator(b->type, t, b->cdr);    ret = low_match_types(a, t, flags);    free_type(t);    return ret;    } +  +  case PIKE_T_TRANSITIVE: +  { +  /* FIXME */ +  return a;    } -  +  }       /* '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:4498:    struct pike_type *t = b->car;    if ((t->type >= '0') && (t->type <= '9')) {    t = ((flags & LE_A_B_SWAPPED)?a_markers:b_markers)[t->type - '0'];    if (!t) t = zero_type_string;    }    t = apply_type_operator(b->type, t, b->cdr);    ret = low_pike_types_le(a, t, array_cnt, flags);    free_type(t);    return ret;    } +  +  case PIKE_T_TRANSITIVE: +  { +  /* FIXME */ +  return 1;    } -  +  }      #ifdef TYPE_GROUPING    if (a->type != T_OR) {    flags &= ~LE_A_GROUPED;    }   #endif       switch(a->type & 0xff)    {    case T_AND:
pike.git/src/pike_types.cmod:4724:    struct pike_type *t = a->car;    if ((t->type >= '0') && (t->type <= '9')) {    t = ((flags & LE_A_B_SWAPPED)?b_markers:a_markers)[t->type - '0'];    if (!t) t = zero_type_string;    }    t = apply_type_operator(a->type, t, a->cdr);    ret = low_pike_types_le(t, b, array_cnt, flags);    free_type(t);    return ret;    } +  +  case PIKE_T_TRANSITIVE: +  { +  /* FIXME */ +  return 1;    } -  +  }       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:5225:    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 & 0xff)    { +  case PIKE_T_TRANSITIVE: +  a = a->car; +  if (a->type != T_FUNCTION) { +  if (a->type == T_MANY) { +  a = a->cdr; +  push_finished_type_with_markers(a, a_markers, 0); +  return 1; +  } +  return low_get_return_type(a, mixed_type_string); +  } +  /* FALLTHRU */    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 */    case T_MANY:
pike.git/src/pike_types.cmod:6000:    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 PIKE_T_TRANSITIVE: +  num = low_count_arguments(q->car); +  if (num == MAX_INT32) return num; +  if (num < 0) return num; +  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:6147:    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 PIKE_T_TRANSITIVE: +  if (arg_no < 0) { +  fun = fun->cdr; +  goto loop; +  } +  +  tmp = fun->car; +  add_ref(tmp); +  +  do { +  tmp2 = new_get_return_type(tmp, 0); +  if (tmp2) { +  /* Apply fun->cdr with tmp2. */ +  struct pike_type *tmp3 = +  low_new_check_call(fun->cdr, tmp2, 0, NULL); +  free_type(tmp2); +  if (!tmp3) { +  tmp3 = get_argument_type(tmp, arg_no); +  free_type(tmp); +  return tmp3; +  } +  tmp2 = or_pike_types(tmp, tmp3, 1); +  free_type(tmp); +  free_type(tmp3); +  tmp = tmp2; +  tmp2 = NULL; +  } +  +  if (!arg_no) break; +  +  tmp2 = low_new_check_call(tmp, mixed_type_string, 0, NULL); +  free_type(tmp); +  if (!tmp2) { +  add_ref(void_type_string); +  return void_type_string; +  } +  tmp = tmp2; +  tmp2 = NULL; +  arg_no--; +  } while(1); +  +  tmp2 = get_argument_type(tmp, 0); +  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:7269:    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_TRANSITIVE: +  tmp = new_get_return_type(fun_type->car, 0); +  if (tmp) { +  tmp2 = low_new_check_call(fun_type->cdr, tmp, 0, NULL); +  free_type(tmp); +  if (tmp2) { +  tmp = or_pike_types(fun_type->car, tmp2, 1); +  free_type(tmp2); +  } else { +  tmp = fun_type->car; +  add_ref(tmp); +  } +  } else { +  tmp = fun_type->car; +  add_ref(tmp); +  } +  tmp2 = lower_new_check_call(tmp, arg_type, flags, sval CHECK_CALL_ARGS); +  free_type(tmp); +  if (tmp2) { +  type_stack_mark(); +  push_finished_type(fun_type->cdr); +  push_finished_type(tmp2); +  push_type(PIKE_T_TRANSITIVE); +  free_type(tmp2); +  tmp2 = pop_unfinished_type(); +  } +  return tmp2; +     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:7755:    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;    +  case PIKE_T_TRANSITIVE: +  /* NB: Not 100% correct, but good enough for most purposes. */ +  fun_type = fun_type->car; +  goto loop; +     default:    /* Not a callable. */    break;    }       if (!res) {   #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "Failed.\n");    }
pike.git/src/pike_types.cmod:7944:    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 PIKE_T_TRANSITIVE: +  tmp = new_get_return_type(fun_type->car, 0); +  +  if (!tmp) { +  fun_type = fun_type->car; +  goto loop; +  } +  +  tmp2 = low_new_check_call(fun_type->cdr, tmp, 0, NULL); +  free_type(tmp); +  tmp = NULL; +  +  if (!tmp2) { +  fun_type = fun_type->car; +  goto loop; +  } +  +  tmp = or_pike_types(fun_type->car, tmp2, 1); +  free_type(tmp2); +  res = get_first_arg_type(tmp, flags); +  free_type(tmp); +  return res; +     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:8448:    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;    } +  +  case PIKE_T_TRANSITIVE: +  yytype_report(REPORT_WARNING, NULL, 0, NULL, +  NULL, 0, a, +  0, "Zapping the return value for a transitive " +  "function is not supported."); +  break;    }   /* 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,
pike.git/src/pike_types.cmod:8944:    break;    case T_OR:    case T_AND:    /* Order independant */    /* FALLTHRU */       case T_MANY:    case T_TUPLE:    case T_MAPPING:    case PIKE_T_RING: +  case PIKE_T_TRANSITIVE:    /* Order dependant */    low_make_pike_type(type_string+1, cont);    low_make_pike_type(*cont, cont);    push_reverse_type(type);    break;    case PIKE_T_FUNCTION_ARG:    low_make_pike_type(type_string+1, cont);    low_make_pike_type(*cont, cont);    push_reverse_type(T_FUNCTION);    break;
pike.git/src/pike_types.cmod:9221:    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: +  case PIKE_T_TRANSITIVE:    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:9294:    case T_MAPPING:    buffer_add_char(buf, t->type ^ MIN_REF_TYPE);    low_type_to_string(buf, t->car);    t = t->cdr;    goto recurse;       case PIKE_T_RING:    case T_TUPLE:    case T_OR:    case T_AND: +  case PIKE_T_TRANSITIVE:    buffer_add_char(buf, t->type);    low_type_to_string(buf, t->car);    t = t->cdr;    goto recurse;       case T_FLOAT:    case T_ZERO:    buffer_add_char(buf, t->type ^ MIN_REF_TYPE);    break;   
pike.git/src/pike_types.cmod:9633:    if (res) return res;       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 PIKE_T_TRANSITIVE:    res = find_type(t->car, cb);    if (res) return res;    /* FALLTHRU */    case T_SCOPE:    case T_ASSIGN:    case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    case T_ARRAY:    case T_STRING:    return find_type(t->cdr, cb);
pike.git/src/pike_types.cmod:9713:    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: +  case PIKE_T_TRANSITIVE:    if (t->car) {    visit_type_ref (t->car, REF_TYPE_INTERNAL, extra);    }    /* FALLTHRU */    case T_SCOPE:    case T_ASSIGN:    visit_type_ref (t->cdr, REF_TYPE_INTERNAL, extra);    break;    case T_MULTISET:    case T_NOT:
pike.git/src/pike_types.cmod:9795:    break;    case PIKE_T_FUNCTION:    case T_MANY:    case PIKE_T_RING:    case PIKE_T_TUPLE:    case PIKE_T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_ARRAY:    case PIKE_T_STRING: +  case PIKE_T_TRANSITIVE:    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) {
pike.git/src/pike_types.cmod:9890:    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: +  case PIKE_T_TRANSITIVE:    if (t->car) {    debug_gc_check (t->car, " as car in a type");    }    debug_gc_check (t->cdr, " as cdr in a type");    break;    case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:   #ifdef PIKE_DEBUG    /* this is a string and without PIKE_DEBUG    * they are not touched by the GC */