pike.git / src / pike_types.c

version» Context lines:

pike.git/src/pike_types.c:1:   /*\   ||| This file a part of Pike, and is copyright by Fredrik Hubinette   ||| Pike is distributed as GPL (General Public License)   ||| See the files COPYING and DISCLAIMER for more information.   \*/   /**/   #include "global.h" - RCSID("$Id: pike_types.c,v 1.69 1999/11/21 21:10:12 grubba Exp $"); + RCSID("$Id: pike_types.c,v 1.70 1999/11/23 22:35:44 grubba Exp $");   #include <ctype.h>   #include "svalue.h"   #include "pike_types.h"   #include "stralloc.h"   #include "stuff.h"   #include "array.h"   #include "program.h"   #include "constants.h"   #include "object.h"   #include "multiset.h"   #include "mapping.h"   #include "pike_macros.h"   #include "error.h"   #include "las.h"   #include "language.h" -  + #include "lex.h"   #include "pike_memory.h"   #include "bignum.h"      int max_correct_args;      static void internal_parse_type(char **s);   static int type_length(char *t); -  + static int low_pike_types_le(char *a, char *b);      #define TWOT(X,Y) (((X) << 8)+(Y))   #define EXTRACT_TWOT(X,Y) TWOT(EXTRACT_UCHAR(X), EXTRACT_UCHAR(Y))      /*    * basic types are represented by just their value in a string    * basic type are string, int, float, object and program    * arrays are coded like by the value T_ARRAY followed by the    * data type, if the type is not known it is T_MIXED, ie:    * T_ARRAY <data type>
pike.git/src/pike_types.c:46:    * they are coded like this:    * T_FUNCTION <arg type> <arg type> ... <arg type> T_MANY <arg type> <return type>    * note that the type after T_MANY can be T_VOID    * T_MIXED matches anything except T_VOID    * T_UNKNOWN only matches T_MIXED and T_UNKNOWN    * objects are coded thus:    * T_OBJECT <0/1> <program_id>    * ^    * 0 means 'inherits'    * 1 means 'is' +  * Everything except T_VOID matches T_ZERO.    */      struct pike_string *string_type_string;   struct pike_string *int_type_string;   struct pike_string *float_type_string;   struct pike_string *function_type_string;   struct pike_string *object_type_string;   struct pike_string *program_type_string;   struct pike_string *array_type_string;   struct pike_string *multiset_type_string;   struct pike_string *mapping_type_string;   struct pike_string *mixed_type_string;   struct pike_string *void_type_string; -  + struct pike_string *zero_type_string;   struct pike_string *any_type_string;      static struct pike_string *a_markers[10],*b_markers[10];      static void clear_markers(void)   {    unsigned int e;    for(e=0;e<NELEM(a_markers);e++)    {    if(a_markers[e])
pike.git/src/pike_types.c:108:    int_type_string = CONSTTYPE(tInt);    object_type_string = CONSTTYPE(tObj);    program_type_string = CONSTTYPE(tPrg);    float_type_string = CONSTTYPE(tFloat);    mixed_type_string=CONSTTYPE(tMix);    array_type_string=CONSTTYPE(tArray);    multiset_type_string=CONSTTYPE(tMultiset);    mapping_type_string=CONSTTYPE(tMapping);    function_type_string=CONSTTYPE(tFunction);    void_type_string=CONSTTYPE(tVoid); +  zero_type_string=CONSTTYPE(tZero);    any_type_string=CONSTTYPE(tOr(tVoid,tMix));   }      static int type_length(char *t)   {    char *q=t;   one_more_type:    switch(EXTRACT_UCHAR(t++))    {    default:
pike.git/src/pike_types.c:156:    case '5':    case '6':    case '7':    case '8':    case '9':    case T_FLOAT:    case T_STRING:    case T_PROGRAM:    case T_MIXED:    case T_VOID: +  case T_ZERO:    case T_UNKNOWN:    break;       case T_INT:    t+=sizeof(INT32)*2;    break;       case T_OBJECT:    t++;    t+=sizeof(INT32);
pike.git/src/pike_types.c:712: Inside #if defined(PIKE_DEBUG)
   case T_ARRAY: printf("array"); break;    case T_MAPPING: printf("mapping"); break;    case T_MULTISET: printf("multiset"); break;       case T_UNKNOWN: printf("unknown"); break;    case T_MANY: printf("many"); break;    case T_OR: printf("or"); break;    case T_AND: printf("and"); break;    case T_NOT: printf("not"); break;    case T_VOID: printf("void"); break; +  case T_ZERO: printf("zero"); break;    case T_MIXED: printf("mixed"); break;       default: printf("%d",EXTRACT_UCHAR(a+e)); break;    }    }    printf("\n");   }      void simple_describe_type(struct pike_string *s)   {
pike.git/src/pike_types.c:744:       case T_ASSIGN:    my_putchar('(');    my_putchar(EXTRACT_UCHAR(t++));    my_putchar('=');    t=low_describe_type(t);    my_putchar(')');    break;       case T_VOID: my_strcat("void"); break; +  case T_ZERO: my_strcat("zero"); break;    case T_MIXED: my_strcat("mixed"); break;    case T_UNKNOWN: my_strcat("unknown"); break;    case T_INT:    {    INT32 min=extract_type_int(t);    INT32 max=extract_type_int(t+sizeof(INT32));    my_strcat("int");       if(min!=MIN_INT32 || max!=MAX_INT32)    {
pike.git/src/pike_types.c:891:    {    case T_OR:    t++;    tmp=low_compile_type_to_runtime_type(t);    if(tmp == low_compile_type_to_runtime_type(t+type_length(t)))    return tmp;       default:    return T_MIXED;    +  case T_ZERO: +  return T_INT; +     case T_ARRAY:    case T_MAPPING:    case T_MULTISET:       case T_OBJECT:    case T_PROGRAM:    case T_FUNCTION:       case T_STRING:    case T_INT:
pike.git/src/pike_types.c:949:      static void low_or_pike_types(char *t1, char *t2)   {    if(!t1)    {    if(!t2)    push_type(T_VOID);    else    push_unfinished_type(t2);    } -  else if(!t2) +  else if((!t2) || (EXTRACT_UCHAR(t2) == T_ZERO))    {    push_unfinished_type(t1);    } -  +  else if (EXTRACT_UCHAR(t1) == T_ZERO) +  { +  push_unfinished_type(t2); +  }    else if(EXTRACT_UCHAR(t1)==T_MIXED || EXTRACT_UCHAR(t2)==T_MIXED)    {    push_type(T_MIXED);    }    else if(EXTRACT_UCHAR(t1)==T_INT && EXTRACT_UCHAR(t2)==T_INT)    {    INT32 i1,i2;    i1=extract_type_int(t1+1+sizeof(INT32));    i2=extract_type_int(t2+1+sizeof(INT32));    push_type_int(MAXIMUM(i1,i2));
pike.git/src/pike_types.c:1049:   static int lower_and_pike_types(char *t1, char *t2)   {    int is_complex = 0;    while(EXTRACT_UCHAR(t1)==T_OR)    {    t1++;    is_complex |= lower_and_pike_types(t1, t2);    t1 += type_length(t1);    }    switch(EXTRACT_UCHAR(t1)) { +  case T_ZERO:    case T_VOID:    break; -  +  case T_PROGRAM:    case T_STRING:    case T_FLOAT:    case T_INT:    even_lower_and_pike_types(t1, t2);    break;    default:    return 1;    }    return is_complex;   }
pike.git/src/pike_types.c:1081:    if (is_complex) {    push_type(T_OR);    } else {    is_complex = 1;    }    }    type += type_length(type);    }    switch(EXTRACT_UCHAR(type)) {    case T_VOID: +  case T_ZERO: +  case T_PROGRAM:    case T_STRING:    case T_FLOAT:    case T_INT:    /* Simple type. Already handled. */    break;    default:    push_unfinished_type(type);    if (is_complex) {    push_type(T_OR);    }    return 1;    }    return is_complex;   }      static void low_and_pike_types(char *t1, char *t2)   { -  if(!t1) +  if(!t1 || EXTRACT_UCHAR(t1) == T_VOID || +  !t2 || EXTRACT_UCHAR(t2) == T_VOID)    { -  if(!t2) +     push_type(T_VOID); -  else -  push_unfinished_type(t2); +     } -  else if(!t2) +  else if(EXTRACT_UCHAR(t1) == T_ZERO || +  EXTRACT_UCHAR(t2) == T_ZERO)    { -  push_unfinished_type(t1); +  push_type(T_ZERO);    }    else if(EXTRACT_UCHAR(t1)==T_MIXED)    {    push_unfinished_type(t2);    }    else if(EXTRACT_UCHAR(t2)==T_MIXED)    {    push_unfinished_type(t1);    } -  else if(EXTRACT_UCHAR(t1)==T_VOID || EXTRACT_UCHAR(t2)==T_VOID) -  { -  push_type(T_VOID); -  } +     else if(EXTRACT_UCHAR(t1)==T_INT && EXTRACT_UCHAR(t2)==T_INT)    {    INT32 i1,i2;    INT32 upper_bound,lower_bound;    i1=extract_type_int(t1+1+sizeof(INT32));    i2=extract_type_int(t2+1+sizeof(INT32));    upper_bound = MINIMUM(i1,i2);       i1=extract_type_int(t1+1);    i2=extract_type_int(t2+1);
pike.git/src/pike_types.c:1144:    push_type_int(upper_bound);    push_type_int(lower_bound);    push_type(T_INT);    } else {    /* No overlap! */    /* FIXME: Warn? */    push_type(T_VOID);    }    }    else if((EXTRACT_UCHAR(t1)==T_STRING && EXTRACT_UCHAR(t2)==T_STRING) || -  (EXTRACT_UCHAR(t1)==T_FLOAT && EXTRACT_UCHAR(t2)==T_FLOAT)) +  (EXTRACT_UCHAR(t1)==T_FLOAT && EXTRACT_UCHAR(t2)==T_FLOAT) || +  (EXTRACT_UCHAR(t1)==T_PROGRAM && EXTRACT_UCHAR(t2)==T_PROGRAM))    {    push_unfinished_type(t1);    } -  +  else if(low_pike_types_le(t1, t2)) +  { +  push_unfinished_type(t1); +  } +  else if(low_pike_types_le(t2, t1)) +  { +  push_unfinished_type(t2); +  }    else    { -  push_type(T_VOID); +  push_type(T_ZERO);       if (lower_and_pike_types(t1, t2)) {    /* t1 contains complex types. */    if (low_and_push_complex_pike_type(t2)) {    /* t2 also contains complex types. */    low_and_push_complex_pike_type(t1);    push_type(T_AND);    push_type(T_OR);    }    }
pike.git/src/pike_types.c:1307:    {    int m=EXTRACT_UCHAR(b)-'0';    if(b_markers[m])    return low_match_types(a, b_markers[m]->str, flags);    else    return low_match_types(a, mixed_type_string->str, flags);    }    }       /* 'mixed' matches anything */ -  if(EXTRACT_UCHAR(a) == T_MIXED && !(flags & A_EXACT)) return a; +     if(EXTRACT_UCHAR(b) == T_MIXED && !(flags & B_EXACT)) return a; -  +  if(EXTRACT_UCHAR(a) == T_ZERO && !(flags & A_EXACT) && +  EXTRACT_UCHAR(b) != T_VOID) return a; +  if(EXTRACT_UCHAR(a) == T_MIXED && !(flags & A_EXACT)) return a; +  if(EXTRACT_UCHAR(b) == T_ZERO && !(flags & B_EXACT) && +  EXTRACT_UCHAR(a) != T_VOID) return a;    -  +     /* Special cases (tm) */    switch(EXTRACT_TWOT(a,b))    {    case TWOT(T_PROGRAM, T_FUNCTION):    case TWOT(T_FUNCTION, T_PROGRAM):    return a;    case TWOT(T_OBJECT, T_FUNCTION):    {    struct pike_string *s;    if((s=low_object_lfun_type(a, LFUN_CALL)))
pike.git/src/pike_types.c:1454:    }          case T_MULTISET:    case T_ARRAY:    if(!low_match_types(++a,++b,flags)) return 0;       case T_FLOAT:    case T_STRING:    case T_PROGRAM: +  case T_ZERO:    case T_VOID:    case T_MIXED:    break;       default:    fatal("error in type string.\n");    }    return ret;   }      /* -  +  * Check the partial ordering relation. +  * +  * mixed +  * +  * int float string program function object +  * +  * zero +  * +  * void +  */ + static int low_pike_types_le(char *a,char *b) + { +  int ret; +  if(a == b) return 1; +  +  switch(EXTRACT_UCHAR(a)) +  { +  case T_AND: +  /* OK if either of the parts is a subset. */ +  /* FIXME: What if b also contains an AND? */ +  a++; +  ret = low_pike_types_le(a,b); +  if(ret) return ret; +  a += type_length(a); +  return low_pike_types_le(a,b); +  +  case T_OR: +  /* OK, if both of the parts are a subset */ +  a++; +  ret=low_pike_types_le(a,b); +  if (!ret) return 0; +  a+=type_length(a); +  return low_pike_types_le(a,b); +  +  case T_NOT: +  return !low_pike_types_le(a+1,b); +  +  case T_ASSIGN: +  ret=low_pike_types_le(a+2,b); +  if(ret && EXTRACT_UCHAR(b)!=T_VOID) +  { +  int m=EXTRACT_UCHAR(a+1)-'0'; +  type_stack_mark(); +  low_or_pike_types(a_markers[m] ? a_markers[m]->str : 0,b); +  if(a_markers[m]) free_string(a_markers[m]); +  a_markers[m]=pop_unfinished_type(); +  } +  return ret; +  +  case '0': case '1': case '2': case '3': case '4': +  case '5': case '6': case '7': case '8': case '9': +  { +  int m=EXTRACT_UCHAR(a)-'0'; +  if(a_markers[m]) +  return low_pike_types_le(a_markers[m]->str, b); +  else +  return low_pike_types_le(mixed_type_string->str, b); +  } +  } +  +  switch(EXTRACT_UCHAR(b)) +  { +  case T_AND: +  /* OK, if a is a subset of both parts. */ +  b++; +  ret = low_pike_types_le(a,b); +  if(!ret) return 0; +  b+=type_length(b); +  return low_pike_types_le(a,b); +  +  case T_OR: +  /* OK if a is a subset of either of the parts. */ +  b++; +  ret=low_pike_types_le(a,b); +  if (ret) return ret; +  b+=type_length(b); +  return low_pike_types_le(a,b); +  +  case T_NOT: +  return !low_pike_types_le(a,b+1); +  +  case T_ASSIGN: +  ret=low_pike_types_le(a,b+2); +  if(ret && EXTRACT_UCHAR(a)!=T_VOID) +  { +  int m=EXTRACT_UCHAR(b+1)-'0'; +  type_stack_mark(); +  low_or_pike_types(b_markers[m] ? b_markers[m]->str : 0,a); +  if(b_markers[m]) free_string(b_markers[m]); +  b_markers[m]=pop_unfinished_type(); +  } +  return ret; +  +  case '0': case '1': case '2': case '3': case '4': +  case '5': case '6': case '7': case '8': case '9': +  { +  int m=EXTRACT_UCHAR(b)-'0'; +  if(b_markers[m]) +  return low_pike_types_le(a, b_markers[m]->str); +  else +  return low_pike_types_le(a, mixed_type_string->str); +  } +  +  case T_MIXED: +  /* any_type <= 'mixed' */ +  return 1; +  } +  +  if (EXTRACT_UCHAR(a) == T_MIXED) { +  return 0; +  } +  +  if (EXTRACT_UCHAR(a) == T_VOID) { +  /* void <= any_type */ +  return 1; +  } +  +  if (EXTRACT_UCHAR(b) == T_VOID) { +  return 0; +  } +  +  if (EXTRACT_UCHAR(a) == T_ZERO) { +  /* void <= zero <= any_type */ +  return 1; +  } +  +  if (EXTRACT_UCHAR(b) == T_ZERO) { +  return 0; +  } +  +  /* Special cases (tm) */ +  switch(EXTRACT_TWOT(a,b)) +  { +  case TWOT(T_PROGRAM, T_FUNCTION): +  case TWOT(T_FUNCTION, T_PROGRAM): +  /* FIXME: Not really... Should check the return value. */ +  return 1; +  +  case TWOT(T_OBJECT, T_FUNCTION): +  { +  struct pike_string *s; +  if((s=low_object_lfun_type(a, LFUN_CALL))) +  return low_pike_types_le(s->str,b); +  return 1; +  } +  +  case TWOT(T_FUNCTION, T_OBJECT): +  { +  struct pike_string *s; +  if((s=low_object_lfun_type(b, LFUN_CALL))) +  return low_pike_types_le(a,s->str); +  return 1; +  } +  } +  +  if(EXTRACT_UCHAR(a) != EXTRACT_UCHAR(b)) return 0; +  +  ret=1; +  switch(EXTRACT_UCHAR(a)) +  { +  case T_FUNCTION: +  a++; +  b++; +  while(EXTRACT_UCHAR(a)!=T_MANY || EXTRACT_UCHAR(b)!=T_MANY) +  { +  char *a_tmp,*b_tmp; +  if(EXTRACT_UCHAR(a)==T_MANY) +  { +  a_tmp=a+1; +  }else{ +  a_tmp=a; +  a+=type_length(a); +  } +  +  if(EXTRACT_UCHAR(b)==T_MANY) +  { +  b_tmp=b+1; +  }else{ +  b_tmp=b; +  b+=type_length(b); +  } +  +  if(!low_pike_types_le(a_tmp, b_tmp)) return 0; +  } +  /* check the 'many' type */ +  a++; +  b++; +  if (!low_pike_types_le(a, b)) +  return 0; +  +  a+=type_length(a); +  b+=type_length(b); +  +  /* check the returntype */ +  /* NOTE: The order between a & b is switched. */ +  if(!low_pike_types_le(b,a)) return 0; +  break; +  +  case T_MAPPING: +  /* +  * mapping(A:B) <= mapping(C:D) iff C <= A && B <= D. +  */ +  if(!low_pike_types_le(++b,++a)) return 0; +  return low_pike_types_le(a+type_length(a),b+type_length(b)); +  +  case T_OBJECT: + #if 0 +  if(extract_type_int(a+2) || extract_type_int(b+2)) +  { +  fprintf(stderr,"Type match1: "); +  stupid_describe_type(a,type_length(a)); +  fprintf(stderr,"Type match2: "); +  stupid_describe_type(b,type_length(b)); +  } + #endif +  +  /* object(* 0) matches any object */ +  if(!extract_type_int(b+2)) +  return 1; +  +  if(!extract_type_int(a+2)) +  return 0; +  +  +  /* object(x *) =? object(x *) */ +  if(EXTRACT_UCHAR(a+1) == EXTRACT_UCHAR(b+1)) +  { +  /* x? */ +  if(EXTRACT_UCHAR(a+1)) +  { +  /* object(1 x) =? object(1 x) */ +  if(extract_type_int(a+2) != extract_type_int(b+2)) return 0; +  }else{ +  /* object(0 *) =? object(0 *) */ +  break; +  } +  } +  +  { +  struct program *ap,*bp; +  ap=id_to_program(extract_type_int(a+2)); +  bp=id_to_program(extract_type_int(b+2)); +  +  if(!ap || !bp) break; +  +  if(EXTRACT_UCHAR(a+1)) +  { +  if(!implements(ap,bp)) +  return 0; +  }else{ +  if(!implements(bp,ap)) +  return 0; +  } +  } +  +  break; +  +  case T_INT: +  { +  INT32 amin=extract_type_int(a+1); +  INT32 amax=extract_type_int(a+1+sizeof(INT32)); +  +  INT32 bmin=extract_type_int(b+1); +  INT32 bmax=extract_type_int(b+1+sizeof(INT32)); +  +  if(amin < bmin || amax > bmax) return 0; +  break; +  } +  +  +  case T_MULTISET: +  case T_ARRAY: +  if(!low_pike_types_le(++a,++b)) return 0; +  +  case T_FLOAT: +  case T_STRING: +  case T_PROGRAM: +  case T_ZERO: +  case T_VOID: +  case T_MIXED: +  break; +  +  default: +  fatal("error in type string.\n"); +  } +  return ret; + } +  + /*    * Return the return type from a function call.    */   static int low_get_return_type(char *a,char *b)   {    int tmp;    switch(EXTRACT_UCHAR(a))    {    case T_OR:    {    struct pike_string *o1,*o2;
pike.git/src/pike_types.c:1552:         int match_types(struct pike_string *a,struct pike_string *b)   {    check_type_string(a);    check_type_string(b);    clear_markers();    return 0!=low_match_types(a->str, b->str,0);   }    + int pike_types_le(struct pike_string *a,struct pike_string *b) + { +  check_type_string(a); +  check_type_string(b); +  clear_markers(); +  return low_pike_types_le(a->str, b->str); + }    -  +    #ifdef DEBUG_MALLOC   #define low_index_type(X,Y) ((struct pike_string *)debug_malloc_touch(debug_low_index_type((X),(Y))))   #else   #define low_index_type debug_low_index_type   #endif      /* FIXME, add the index */   static struct pike_string *debug_low_index_type(char *t, node *n)   {    struct program *p;
pike.git/src/pike_types.c:1622:       case T_INT:   #ifdef AUTO_BIGNUM    /* Don't force Gmp.mpz to be loaded here since this function    * is called long before the master object is compiled...    * /Hubbe    */    p=get_auto_bignum_program_or_zero();    goto comefrom_int_index;   #endif +  case T_ZERO:    case T_VOID:    case T_FLOAT:    return 0;       case T_OR:    {    struct pike_string *a,*b;    a=low_index_type(t,n);    t+=type_length(t);    b=low_index_type(t,n);
pike.git/src/pike_types.c:1725:    }    }    reference_shared_string(string_type_string);    return string_type_string;    }    default:    reference_shared_string(mixed_type_string);    return mixed_type_string;       case T_VOID: +  case T_ZERO:    case T_FLOAT:    case T_INT:    return 0;       case T_OR:    {    struct pike_string *a,*b;    a=low_key_type(t,n);    t+=type_length(t);    b=low_key_type(t,n);
pike.git/src/pike_types.c:2093:    if(s->u.integer)    {    type_stack_mark();    /* Fixme, check that the integer is in range of MIN_INT32 .. MAX_INT32!    */    push_type_int(s->u.integer);    push_type_int(s->u.integer);    push_type(T_INT);    return pop_unfinished_type();    }else{ -  ret=mixed_type_string; +  ret=zero_type_string;    }    reference_shared_string(ret);    return ret;       case T_PROGRAM:    {    char *a;    struct pike_string *tmp;    int id=FIND_LFUN(s->u.program,LFUN_CREATE);    if(id>=0)
pike.git/src/pike_types.c:2134:    case T_ARRAY: return "array";    case T_FLOAT: return "float";    case T_FUNCTION: return "function";    case T_INT: return "int";    case T_LVALUE: return "lvalue";    case T_MAPPING: return "mapping";    case T_MULTISET: return "multiset";    case T_OBJECT: return "object";    case T_PROGRAM: return "program";    case T_STRING: return "string"; +  case T_ZERO: return "zero";    case T_VOID: return "void";    default: return "unknown";    }   }      void cleanup_pike_types(void)   {    free_string(string_type_string);    free_string(int_type_string);    free_string(float_type_string);    free_string(function_type_string);    free_string(object_type_string);    free_string(program_type_string);    free_string(array_type_string);    free_string(multiset_type_string);    free_string(mapping_type_string);    free_string(mixed_type_string);    free_string(void_type_string); -  +  free_string(zero_type_string);    free_string(any_type_string);   }         int type_may_overload(char *type, int lfun)   {    switch(EXTRACT_UCHAR(type++))    {    case T_ASSIGN:    return type_may_overload(type+1,lfun);