pike.git / src / pike_types.cmod

version» Context lines:

pike.git/src/pike_types.cmod:4646:    type_stack_mark();    push_finished_type(b);    push_finished_type(a);    push_binop(op);    return pop_unfinished_type();       case TWOT(T_FUNCTION, T_FUNCTION):    case TWOT(T_FUNCTION, T_MANY):    case TWOT(T_MANY, T_FUNCTION):    case TWOT(T_MANY, T_MANY): +  { +  int nargs; +  struct pike_type *ai = a; +  struct pike_type *bi = b; +  enum pt_cmp_flags avoidable = 0; +  enum pt_cmp_flags bvoidable = 0; +  +  type_stack_mark(); +  +  switch(op) { +  case PT_BINOP_AND:    /* NB: For simplicity in the (common case)    * many(assign(m, mixed), m),    * we expand the many node (as required) to    * function(assign(m, mixed), many(assign(m, mixed), m)),    * and leave it to the evaluator to join the multiple    * assignments with or. The alternative (and stricter) would    * be to allocate a new marker for each step of the expansion    * and to have explicit or nodes: -  * function(assign(m1, mixed), many(assign(m2, mixed), or(m1, m2))). +  * function(assign(m1, mixed), +  * many(assign(m2, mixed), or(m1, m2))).    */ -  { -  int nargs; -  struct pike_type *ai = a; -  struct pike_type *bi = b; -  -  type_stack_mark(); -  +     while(1) {    /* Invariant:    * ai->type and bi->type are either T_FUNCTION or T_MANY.    */ -  enum pt_cmp_flags avoidable = 0; -  enum pt_cmp_flags bvoidable = 0; +        /* Check the argument. */       /* NB: The MANY argument is always voidable. */    if (ai->type == T_MANY) avoidable |= PT_FLAG_CMP_VOIDABLE;    if (bi->type == T_MANY) bvoidable |= PT_FLAG_CMP_VOIDABLE;    -  /* FIXME: Only use implicit nullable for legacy types. */ -  tmp = low_type_binop(op, ai->car, bi->car, remap, + #if 0 +  fprintf(stderr, "arg_check(op: 0x%x, ", op); +  simple_describe_type(ai); +  fprintf(stderr, " (%d), ", avoidable); +  simple_describe_type(bi); +  fprintf(stderr, " (%d))\n\n", bvoidable); + #endif +  +  /* FIXME: Use implicit nullable only for legacy types. */ +  /* NOTE: Intentional use of PT_BINOP_OR below! +  * Note that for function types a larger type for +  * the arguments implies that the function type +  * is stricter. This is a DeMorgan-style effect +  * due to the implicit ALL and EXIST operators +  * for arguments in function types. Eg there are +  * many more functions that accept 0 as an argument +  * than there are functions that accept any integer. +  * Thus function(int:mixed) is a stricter type +  * than function(zero:mixed). +  */ +  tmp = low_type_binop(PT_BINOP_OR, ai->car, bi->car, remap,    avoidable | PT_FLAG_CMP_NULLABLE,    bvoidable | PT_FLAG_CMP_NULLABLE,    remap_flags);       /* 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:4708:    }    break;    }       if (remap_flags & PT_FLAG_REMAP_TRACE) {    fprintf(stderr, "tmp: ");    simple_describe_type(tmp);    fprintf(stderr, "\n");    }    -  switch(op) { -  case PT_BINOP_AND: -  if (!tmp) { -  if (avoidable && bvoidable) { -  /* NB: The VOIDABLE flag only affects comparisons with -  * explicit void. If both arguments have implicit void, -  * and nothing other in common, we arrive here. -  */ -  push_type(T_VOID); -  } else { -  goto function_fail; -  } -  } else { +     push_finished_type(tmp);    free_type(tmp); -  } +        if (avoidable && bvoidable) {    /* Time to check the return types. */       if (!aret) aret = ai->cdr;    if (!bret) bret = bi->cdr;       tmp = low_type_binop(op, aret, bret, remap,    0, 0, remap_flags);   
pike.git/src/pike_types.cmod:4754:    free_type(tmp);       nargs--;    push_reverse_type(T_MANY);       while (nargs--) {    push_reverse_type(T_FUNCTION);    }    return pop_unfinished_type();    } +  }    break; -  +     case PT_BINOP_MINUS:    /* Subtraction (A - B)    *    * The result is the subset of function A where at least one    * of the arguments or the return type differs from function B.    *    * T_FUNCTION(A, X) - T_FUNCTION(B, Y) ==    * T_OR(T_FUNCTION(A - B, X), T_FUNCTION(A, X - Y))    *    * T_FUNCTION(A, X) - T_MANY(T_VOID, Y) ==
pike.git/src/pike_types.cmod:4798:    * T_OR(T_FUNCTION(A, T_MANY(A, X)),    * T_MANY(T_VOID, X - Y))    *    * T_MANY(A, X) - T_MANY(~A, Y) == T_MANY(A, X - Y)    *    * T_MANY(A, X) - T_MANY(B, Y) ==    * T_OR(T_MANY(A, X - Y),    * T_AND(T_MANY(A, X),    * T_NOT(T_MANY(T_NOT(A - B), T_MIXED))))    */ +  +  /* Check the argument. */ +  +  /* NB: The MANY argument is always voidable. */ +  if (ai->type == T_MANY) avoidable |= PT_FLAG_CMP_VOIDABLE; +  if (bi->type == T_MANY) bvoidable |= PT_FLAG_CMP_VOIDABLE; +  + #if 0 +  fprintf(stderr, "arg_check(op: 0x%x, ", op); +  simple_describe_type(ai); +  fprintf(stderr, " (%d), ", avoidable); +  simple_describe_type(bi); +  fprintf(stderr, " (%d))\n\n", bvoidable); + #endif +  +  /* FIXME: Use implicit nullable only for legacy types. */ +  tmp = low_type_binop(op, ai->car, bi->car, remap, +  avoidable | PT_FLAG_CMP_NULLABLE, +  bvoidable | PT_FLAG_CMP_NULLABLE, +  remap_flags); +  +  /* Advance to the next argument. */ +  if (ai->type == T_FUNCTION) { +  ai = ai->cdr; +  } +  if (bi->type == T_FUNCTION) { +  bi = bi->cdr; +  } +  if ((ai->type != T_FUNCTION) && (ai->type != T_MANY)) { +  if (aret) { +  Pike_fatal("Unsupported type operation.\n"); +  } +  break; +  } +  if ((bi->type != T_FUNCTION) && (bi->type != T_MANY)) { +  if (bret) { +  Pike_fatal("Unsupported type operation.\n"); +  } +  break; +  } +  +  if (remap_flags & PT_FLAG_REMAP_TRACE) { +  fprintf(stderr, "tmp: "); +  simple_describe_type(tmp); +  fprintf(stderr, "\n"); +  } +     if (avoidable && bvoidable) {    /* FIXME: What if tmp only differs due to remapping? */    if (tmp && tmp->type == T_VOID) {    free_type(tmp);    tmp = NULL;    }    if (tmp != a->car) {    if (!tmp) {    tmp = low_type_binop(op, a->cdr, b->cdr, remap,    PT_FLAG_CMP_VOIDABLE,
pike.git/src/pike_types.cmod:4901:    push_type(T_FUNCTION);    free_type(tmp);    }    nargs = peek_stack_mark();    if (!nargs) {    pop_stack_mark();    return NULL;    }    while (nargs-- > 1) push_type(T_OR);    return pop_unfinished_type(); -  -  default: -  Pike_fatal("Unsupported.\n"); +     }    -  if (avoidable && bvoidable) break; -  } -  +     complex_function:       nargs = peek_stack_mark();    if (op != PT_BINOP_AND) {    nargs = 0;    ai = a;    bi = b;    }       /* Either of a and/or b is a complex type. */