Branch: Tag:

2020-07-13

2020-07-13 07:09:46 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Compiler [Typechecker]: Support more complex function types.

Support type nodes other than T_FUNCTION and T_MANY in the cdr
of T_FUNCTION nodes.

Needed for #10048.

193:    case PIKE_T_INT_UNTYPED: return "PIKE_T_INT_UNTYPED";    case PIKE_T_GET_SET: return "PIKE_T_GET_SET";    case PIKE_T_FREE: return "PIKE_T_FREE"; +  case PIKE_T_FUNCTION_ARG: return "PIKE_T_FUNCTION_ARG";    case PIKE_T_ATTRIBUTE: return "PIKE_T_ATTRIBUTE";    case PIKE_T_NSTRING: return "PIKE_T_NSTRING";    case PIKE_T_LSTRING: return "PIKE_T_LSTRING";
2000:    e+=sizeof(INT32)+1;    break;    case T_FUNCTION: fprintf(stderr, "function"); break; +  case PIKE_T_FUNCTION_ARG: fprintf(stderr, "function_arg"); break;    case T_ARRAY: fprintf(stderr, "array"); break;    case T_MAPPING: fprintf(stderr, "mapping"); break;    case T_MULTISET: fprintf(stderr, "multiset"); break;
2210:    while(s->type == T_FUNCTION) {    simple_describe_type(s->car);    s = s->cdr; -  while(s->type == T_ASSIGN) { -  fprintf(stderr, "%"PRINTPTRDIFFT"d = ", CAR_TO_INT(s)); -  s = s->cdr; -  } +     if ((s->type == T_FUNCTION) ||    (s->car->type != T_VOID)) {    fprintf(stderr, ", ");    }    } -  +  if (s->type != T_MANY) { +  fprintf(stderr, ", @"); +  simple_describe_type(s); +  fprintf(stderr, ")"); +  } else {    if (s->car->type != T_VOID) {    simple_describe_type(s->car);    fprintf(stderr, "...");
2226:    fprintf(stderr, ":");    simple_describe_type(s->cdr);    fprintf(stderr, ")"); +  }    break;    case T_ARRAY: /* FIXME: cdr */    fprintf(stderr, "array(");
2489:    } else {    int arg = 0;    string_builder_strcat(s, "function("); -  while(t->type != T_MANY) +  while(t->type == T_FUNCTION)    {    if(arg++) string_builder_strcat(s, ", ");    low_describe_type(s, t->car);    t = t->cdr; -  while(t->type == T_ASSIGN) { -  string_builder_sprintf(s, "%c=", '0' + CAR_TO_INT(t)); -  t = t->cdr; +     } -  } +  if (t->type != T_MANY) { +  string_builder_sprintf(s, ", @%T", t); +  } else {    if(t->car->type != T_VOID)    {    if(arg++) string_builder_strcat(s, ", ");    low_describe_type(s, t->car);    string_builder_strcat(s, " ...");    } -  string_builder_sprintf(s, " : %T)", t->cdr); +  t = t->cdr; +  string_builder_sprintf(s, " : %T)", t);    } -  +  }    break;    }   
3793:    case TWOT(T_MANY, T_MANY):    ret = a;    correct_args=0; -  while ((a->type != T_MANY) || (b->type != T_MANY)) +  while ((a->type == T_FUNCTION) || (b->type == T_FUNCTION))    {    struct pike_type *a_tmp, *b_tmp;    -  +  if ((a->type != T_FUNCTION) && (a->type != T_MANY)) break; +  if ((b->type != T_FUNCTION) && (b->type != T_MANY)) break; +     a_tmp = a->car;    if (a->type == T_FUNCTION)    {
3816:    if(!(flags & NO_MAX_ARGS))    max_correct_args=correct_args;    } +  +  if ((a->type != T_MANY) || (b->type != T_MANY)) { +  /* Handle the generic case. */ +  return low_match_types(a, b, flags); +  } +     /* check the 'many' type */    if(b->car->type != T_VOID &&    a->car->type != T_VOID)
4536:    *    * FIXME: Enforcing of all required arguments?    */ -  while((a->type != T_MANY) || (b->type != T_MANY)) +  while((a->type == T_FUNCTION) || (b->type == T_FUNCTION))    {    struct pike_type *a_tmp, *b_tmp;    -  +  if ((a->type != T_FUNCTION) && (a->type != T_MANY)) break; +  if ((b->type != T_FUNCTION) && (b->type != T_MANY)) break; +     a_tmp = a->car;    if (a->type == T_FUNCTION)    {
4565:    }    }    } +  +  if ((a->type != T_MANY) || (b->type != T_MANY)) { +  /* Handle the generic case. */ +  return low_pike_types_le(a, b, array_cnt, flags); +  } +     /* FALLTHRU */    case TWOT(T_MANY, T_MANY):    /* check the 'many' type */
4855:    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:    a = a->cdr;
5553:    ;    if (!type) return 0;    +  if (type->type != T_MANY) return 0; +     /* FALLTHRU */       case T_MANY:
5618:    num++;    q = q->cdr;    } +  +  if (q->type != T_MANY) { +  num2 = low_count_arguments(q); +  if (num2 == MAX_INT32) return num2; +  if (num2 < 0) { +  num += ~num2; +  return ~num; +  } +  return num + num2; +  } +     /* FALLTHRU */    case T_MANY:    q = q->car;
6030:    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;
8485:    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;    case T_FUNCTION:    low_make_function_type(type_string+1, cont);    break;