pike.git / src / pike_types.cmod

version» Context lines:

pike.git/src/pike_types.cmod:10833:      /* Get the resulting type from a soft cast.    *    * Flags:    * 1 SOFT_WEAKER Weaker type.    */   struct pike_type *soft_cast(struct pike_type *soft_type,    struct pike_type *orig_type,    int flags)   { - #if 1 +     if (flags & SOFT_WEAKER) {    return type_binop(PT_BINOP_AND, orig_type, soft_type,    PT_FLAG_CMP_NULLABLE, 0, 0);    } else {    return type_binop(PT_BINOP_AND, orig_type, soft_type, 0, 0, 0);    } - #else -  struct pike_type *res = NULL; -  struct pike_type *tmp = NULL; -  struct pike_type *tmp2 = NULL; -  struct pike_type *tmp3 = NULL; -  -  if (soft_type == orig_type) { -  copy_pike_type(res, soft_type); -  return res; +    }    -  loop: -  switch(soft_type->type) { -  case T_OR: -  tmp = soft_cast(soft_type->car, orig_type, flags); -  if (tmp == orig_type) return tmp; -  tmp2 = soft_cast(soft_type->cdr, orig_type, flags); -  if (tmp2 == orig_type) { -  res = tmp2; -  tmp2 = NULL; -  } else { -  res = or_pike_types(tmp, tmp2, 1); -  } -  break; -  case T_AND: -  /* FIXME: Make stricter analogous to OR above. */ -  res = and_pike_types(tmp = soft_cast(soft_type->car, orig_type, flags), -  tmp2 = soft_cast(soft_type->cdr, orig_type, flags)); -  break; -  case T_SCOPE: -  case T_ASSIGN: -  case PIKE_T_NAME: -  soft_type = soft_type->cdr; -  goto loop; -  /* FIXME: TUPLE, RING */ -  case PIKE_T_ATTRIBUTE: -  if ((res = soft_cast(soft_type->cdr, orig_type, flags))) { -  type_stack_mark(); -  push_finished_type(res); -  push_type_attribute((struct pike_string *)soft_type->car); -  free_type(res); -  res = pop_unfinished_type(); -  } -  return res; -  case T_MIXED: -  if (flags & SOFT_WEAKER) { -  copy_pike_type(res, soft_type); -  } else if (orig_type->type == T_VOID) { -  copy_pike_type(res, zero_type_string); -  } else { -  copy_pike_type(res, orig_type); -  } -  break; -  case T_ZERO: -  if (!(flags & SOFT_WEAKER) || (orig_type->type == T_VOID)) { -  copy_pike_type(res, soft_type); -  } else { -  copy_pike_type(res, orig_type); -  } -  break; -  } -  if (!res) { -  loop2: -  switch(orig_type->type) { -  case T_OR: -  tmp = soft_cast(soft_type, orig_type->car, flags); -  if (tmp == soft_type) return tmp; -  tmp2 = soft_cast(soft_type, orig_type->cdr, flags); -  if (tmp2 == soft_type) { -  res = tmp2; -  tmp2 = NULL; -  } else { -  res = or_pike_types(tmp, tmp2, 1); -  } -  break; -  case T_AND: -  /* Note: We need to handle T_NOT here. */ -  if (orig_type->car->type != T_NOT) { -  tmp = soft_cast(soft_type, orig_type->car, flags); -  if (!tmp) return NULL; -  if (tmp == orig_type->car) { -  /* The original type is stricter than the soft type. */ -  free_type(tmp); -  add_ref(orig_type); -  return orig_type; -  } -  } -  if (orig_type->cdr->type != T_NOT) { -  tmp2 = soft_cast(soft_type, orig_type->cdr, flags); -  if (!tmp2) { -  if (tmp) free_type(tmp); -  return NULL; -  } -  if (tmp2 == orig_type->cdr) { -  /* The original type is stricter than the soft type. */ -  if (tmp) free_type(tmp); -  free_type(tmp2); -  add_ref(orig_type); -  return orig_type; -  } -  } -  res = and_pike_types(tmp?tmp:orig_type->car, tmp2?tmp2:orig_type->cdr); -  break; -  case T_SCOPE: -  if ((res = soft_cast(soft_type, orig_type->cdr, flags))) { -  type_stack_mark(); -  push_finished_type(res); -  push_scope_type(CAR_TO_INT(orig_type)); -  free_type(res); -  res = pop_unfinished_type(); -  } -  return res; -  case T_ASSIGN: -  case PIKE_T_NAME: -  orig_type = orig_type->cdr; -  goto loop2; -  case PIKE_T_ATTRIBUTE: -  if ((res = soft_cast(soft_type, orig_type->cdr, flags))) { -  type_stack_mark(); -  push_finished_type(res); -  push_type_attribute((struct pike_string *)orig_type->car); -  free_type(res); -  res = pop_unfinished_type(); -  } -  return res; -  case T_MIXED: -  if (flags & SOFT_WEAKER) { -  copy_pike_type(res, orig_type); -  } else { -  copy_pike_type(res, soft_type); -  } -  break; -  case T_VOID: -  case T_ZERO: -  if (flags & SOFT_WEAKER) { -  copy_pike_type(res, soft_type); -  } else { -  copy_pike_type(res, zero_type_string); -  } -  break; -  } -  } -  if (!res) { -  switch(soft_type->type) { -  case T_VOID: -  if (orig_type->type == T_VOID) { -  copy_pike_type(res, soft_type); -  } else { -  return NULL; -  } -  break; -  case T_TYPE: -  /* Convert to a function returning the subtype and retry. */ -  type_stack_mark(); -  push_finished_type(soft_type->car); -  push_type(T_VOID); -  push_type(T_MANY); -  push_type(T_MIXED); -  push_type(T_FUNCTION); -  tmp = pop_unfinished_type(); -  res = soft_cast(tmp, orig_type, flags); -  break; -  -  case T_PROGRAM: -  /* Convert to a function returning an object. */ -  copy_pike_type(tmp3, soft_type->car); /* Return type */ -  if ((tmp2 = low_object_lfun_type(tmp3, LFUN_CREATE))) { -  soft_type = tmp2; -  tmp2 = NULL; -  } else { -  /* FIXME: Multiple cases. */ -  soft_type = function_type_string; -  } -  /* FALLTHRU */ -  case T_FUNCTION: -  case T_MANY: -  { -  int array_cnt = 0; -  int loop_cnt = 0; -  while(orig_type->type == T_ARRAY) { -  array_cnt++; -  orig_type = orig_type->cdr; -  } -  if (orig_type->type == T_PROGRAM) { -  copy_pike_type(tmp, orig_type->car); /* Return type */ -  if ((tmp2 = low_object_lfun_type(tmp, LFUN_CREATE))) { -  orig_type = tmp2; -  tmp2 = NULL; -  } else { -  /* FIXME: Multiple cases. */ -  tmp2 = soft_type; -  while(tmp2->type == T_FUNCTION) tmp2 = tmp2->cdr; -  if (tmp2->type == T_MANY) { -  if ((tmp2 = soft_cast(tmp2->car, tmp, flags ^ SOFT_WEAKER))) { -  /* FIXME: Adjust the return type to tmp2! */ -  copy_pike_type(res, soft_type); -  } -  } else { -  tmp2 = NULL; -  copy_pike_type(res, soft_type); -  } -  break; -  } -  } else if (orig_type->type == T_OBJECT) { -  if ((tmp = low_object_lfun_type(orig_type, LFUN_CALL))) { -  orig_type = tmp; -  tmp = NULL; -  } else { -  /* FIXME: Multiple cases. */ -  copy_pike_type(res, orig_type); -  break; -  } -  } -  if ((orig_type->type & PIKE_T_MASK) == PIKE_T_OPERATOR) { -  /* Assume ok. */ -  copy_pike_type(res, orig_type); -  break; -  } -  /* FIXME: Loop above until function? */ -  if ((orig_type->type != T_FUNCTION) && -  (orig_type->type != T_MANY)) { -  /* Failure. */ -  break; -  } -  type_stack_mark(); -  while((soft_type->type == T_FUNCTION) || -  (orig_type->type == T_FUNCTION)) { -  if ((soft_type->type != T_FUNCTION) && -  (soft_type->type != T_MANY)) break; -  if ((orig_type->type != T_FUNCTION) && -  (orig_type->type != T_MANY)) break; -  if (!(tmp2 = soft_cast(soft_type->car, orig_type->car, -  flags ^ SOFT_WEAKER))) { -  goto function_cast_fail; -  } -  if (tmp2 != void_type_string) { -  push_finished_type(tmp2); -  loop_cnt++; -  } -  free_type(tmp2); -  tmp2 = NULL; -  if (soft_type->type == T_FUNCTION) soft_type = soft_type->cdr; -  if (orig_type->type == T_FUNCTION) orig_type = orig_type->cdr; -  } -  if ((orig_type->type == T_MANY) && -  (soft_type->type == T_MANY)) { -  if (!(tmp2 = soft_cast(soft_type->car, orig_type->car, -  flags ^ SOFT_WEAKER))) { -  goto function_cast_fail; -  } -  push_finished_type(tmp2); -  free_type(tmp2); -  tmp2 = NULL; -  -  /* Note: Special case for the return type in case of create(). */ -  if (tmp) { -  orig_type = tmp; -  } else { -  orig_type = orig_type->cdr; -  } -  if (tmp3) { -  soft_type = tmp3; -  } else { -  soft_type = soft_type->cdr; -  } -  if (!(tmp2 = soft_cast(soft_type, orig_type, flags))) { -  goto function_cast_fail; -  } -  push_finished_type(tmp2); -  free_type(tmp2); -  tmp2 = NULL; -  -  while(array_cnt--) push_unlimited_array_type(T_ARRAY); -  push_reverse_type(T_MANY); -  } else { -  /* Some kind of complex function type. */ -  /* FIXME: Handle the case where tmp != NULL */ -  push_finished_type(orig_type); -  push_finished_type(soft_type); -  push_type(T_AND); -  -  while(array_cnt--) push_unlimited_array_type(T_ARRAY); -  } -  while(loop_cnt--) push_reverse_type(T_FUNCTION); -  res = pop_unfinished_type(); -  break; -  } -  function_cast_fail: -  type_stack_pop_to_mark(); -  break; -  case T_NOT: /* FIXME. */ -  default: -  if (soft_type->type != orig_type->type) break; -  switch(soft_type->type) { -  case T_MAPPING: -  type_stack_mark(); -  if ((tmp = soft_cast(soft_type->car, orig_type->car, -  flags ^ SOFT_WEAKER))) { -  push_finished_type(tmp); -  } else { -  push_finished_type(zero_type_string); -  } -  if ((tmp2 = soft_cast(soft_type->cdr, orig_type->cdr, flags))) { -  push_finished_type(tmp2); -  } else { -  push_finished_type(zero_type_string); -  } -  push_reverse_type(T_MAPPING); -  res = pop_unfinished_type(); -  break; -  case T_MULTISET: -  case T_TYPE: -  type_stack_mark(); -  if ((tmp = soft_cast(soft_type->car, orig_type->car, flags))) { -  push_finished_type(tmp); -  } else if (flags & SOFT_WEAKER) { -  push_finished_type(mixed_type_string); -  } else { -  push_finished_type(zero_type_string); -  } -  push_type(soft_type->type); -  res = pop_unfinished_type(); -  break; -  case T_FLOAT: -  copy_pike_type(res, soft_type); -  break; -  case T_ARRAY: -  type_stack_mark(); -  if ((tmp = soft_cast(soft_type->cdr, orig_type->cdr, flags))) { -  push_finished_type(tmp); -  } else if (flags & SOFT_WEAKER) { -  push_finished_type(mixed_type_string); -  } else { -  push_finished_type(zero_type_string); -  } -  if (orig_type->type == T_ARRAY) { -  if ((tmp2 = soft_cast(soft_type->car, orig_type->car, flags))) { -  push_finished_type(tmp2); -  } else { -  push_finished_type(orig_type->car); -  } -  } else { -  push_finished_type(soft_type->car); -  } -  push_type(T_ARRAY); -  res = pop_unfinished_type(); -  break; -  case T_STRING: -  tmp = soft_cast(soft_type->cdr, orig_type->cdr, flags); -  if (!tmp) return NULL; -  type_stack_mark(); -  push_finished_type(tmp); -  if (orig_type->type == T_STRING) { -  if ((tmp2 = soft_cast(soft_type->car, orig_type->car, flags))) { -  push_finished_type(tmp2); -  } else { -  push_finished_type(orig_type->car); -  } -  } else { -  push_finished_type(soft_type->car); -  } -  push_type(T_STRING); -  res = pop_unfinished_type(); -  break; -  case T_INT: -  { -  INT32 min, max; -  if (flags & SOFT_WEAKER) { -  if ((min = CAR_TO_INT(soft_type)) > CAR_TO_INT(orig_type)) { -  min = CAR_TO_INT(orig_type); -  } -  if ((max = CDR_TO_INT(soft_type)) < CDR_TO_INT(orig_type)) { -  max = CDR_TO_INT(orig_type); -  } -  } else { -  if ((min = CAR_TO_INT(soft_type)) < CAR_TO_INT(orig_type)) { -  min = CAR_TO_INT(orig_type); -  } -  if ((max = CDR_TO_INT(soft_type)) > CDR_TO_INT(orig_type)) { -  max = CDR_TO_INT(orig_type); -  } -  if (min > max) break; -  } -  type_stack_mark(); -  push_int_type(min, max); -  res = pop_unfinished_type(); -  break; -  } -  case T_OBJECT: -  if (flags & SOFT_WEAKER) { -  if (!CDR_TO_INT(orig_type)) { -  copy_pike_type(res, orig_type); -  } else if (!CDR_TO_INT(soft_type)) { -  copy_pike_type(res, soft_type); -  } else if (CDR_TO_INT(soft_type) == CDR_TO_INT(orig_type)) { -  if (!CAR_TO_INT(orig_type)) { -  copy_pike_type(res, orig_type); -  } else { -  copy_pike_type(res, soft_type); -  } -  } else if (pike_types_le(soft_type, orig_type, 0, 0)) { -  copy_pike_type(res, orig_type); -  } else if (pike_types_le(orig_type, soft_type, 0, 0)) { -  copy_pike_type(res, soft_type); -  } else { -  copy_pike_type(res, object_type_string); -  } -  } else { -  if (!CDR_TO_INT(orig_type)) { -  copy_pike_type(res, soft_type); -  } else if (!CDR_TO_INT(soft_type)) { -  copy_pike_type(res, orig_type); -  } else if (CDR_TO_INT(soft_type) == CDR_TO_INT(orig_type)) { -  if (CAR_TO_INT(orig_type)) { -  copy_pike_type(res, orig_type); -  } else { -  copy_pike_type(res, soft_type); -  } -  } else if (pike_types_le(soft_type, orig_type, 0, 0)) { -  copy_pike_type(res, soft_type); -  } else if (pike_types_le(orig_type, soft_type, 0, 0)) { -  copy_pike_type(res, orig_type); -  } -  } -  break; -  } -  break; -  } -  } -  if (tmp) free_type(tmp); -  if (tmp2) free_type(tmp2); -  if (tmp3) free_type(tmp3); -  return res; - #endif - } -  +    /**    * Check whether sval is a valid value for a variable of    * type type.    *    * Returns 1 if ok, and 0 (zero) otherwise.    */   static int match_type_svalue(struct pike_type *type,    int flags,    struct svalue *sval)   {