Branch: Tag:

1999-11-23

1999-11-23 22:35:44 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Added T_ZERO and pike_types_le().

Rev: src/pike_types.c:1.70

5:   \*/   /**/   #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"
21:   #include "error.h"   #include "las.h"   #include "language.h" + #include "lex.h"   #include "pike_memory.h"   #include "bignum.h"   
28:      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))
53:    * ^    * 0 means 'inherits'    * 1 means 'is' +  * Everything except T_VOID matches T_ZERO.    */      struct pike_string *string_type_string;
66:   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];
115:    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));   }   
163:    case T_PROGRAM:    case T_MIXED:    case T_VOID: +  case T_ZERO:    case T_UNKNOWN:    break;   
719: Inside #if defined(PIKE_DEBUG)
   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;
751:    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:
898:    default:    return T_MIXED;    +  case T_ZERO: +  return T_INT; +     case T_ARRAY:    case T_MAPPING:    case T_MULTISET:
956:    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);
1056:    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:
1088:    }    switch(EXTRACT_UCHAR(type)) {    case T_VOID: +  case T_ZERO: +  case T_PROGRAM:    case T_STRING:    case T_FLOAT:    case T_INT:
1105:      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)    {
1124:    {    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;
1151:    }    }    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. */
1314:    }       /* '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))    {
1461:    case T_FLOAT:    case T_STRING:    case T_PROGRAM: +  case T_ZERO:    case T_VOID:    case T_MIXED:    break;
1472:   }      /* +  * 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)
1559:    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
1629: Inside #if defined(AUTO_BIGNUM)
   p=get_auto_bignum_program_or_zero();    goto comefrom_int_index;   #endif +  case T_ZERO:    case T_VOID:    case T_FLOAT:    return 0;
1732:    return mixed_type_string;       case T_VOID: +  case T_ZERO:    case T_FLOAT:    case T_INT:    return 0;
2100:    push_type(T_INT);    return pop_unfinished_type();    }else{ -  ret=mixed_type_string; +  ret=zero_type_string;    }    reference_shared_string(ret);    return ret;
2141:    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";    }
2159:    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);   }