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.95 1999/12/14 14:55:57 hubbe Exp $"); + RCSID("$Id: pike_types.c,v 1.96 1999/12/15 01:14:17 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"
pike.git/src/pike_types.c:25:   #include "pike_memory.h"   #include "bignum.h"   #include "main.h"      /* #define PIKE_TYPE_DEBUG */      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); + static int low_pike_types_le(char *a, char *b, int array_cnt);      #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, type, 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:50:    * functions are _very_ special:    * 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 'implements' -  * 1 means 'inherits' +  * 1 means 'is' (aka 'clone of')    * Integers are encoded as:    * T_INT <min> <max>    * 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;
pike.git/src/pike_types.c:770: Inside #if defined(PIKE_DEBUG)
   printf("(%ld..%ld)",(long)min,(long)max);    e+=sizeof(INT32)*2;    break;    }    case T_FLOAT: printf("float"); break;    case T_STRING: printf("string"); break;    case T_TYPE: printf("type"); break;    case T_PROGRAM: printf("program"); break;    case T_OBJECT:    printf("object(%s %ld)", -  EXTRACT_UCHAR(a+e+1)?"inherits":"implements", +  EXTRACT_UCHAR(a+e+1)?"is":"implements",    (long)extract_type_int(a+e+2));    e+=sizeof(INT32)+1;    break;    case T_FUNCTION: printf("function"); break;    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;
pike.git/src/pike_types.c:859:    t+=sizeof(INT32)*2;       break;    }    case T_FLOAT: my_strcat("float"); break;    case T_PROGRAM: my_strcat("program"); break;    case T_OBJECT:    if(extract_type_int(t+1))    {    char buffer[100]; -  sprintf(buffer,"object(%s %ld)",*t?"inherits":"implements", +  sprintf(buffer,"object(%s %ld)",*t?"is":"implements",    (long)extract_type_int(t+1));    my_strcat(buffer);    }else{    my_strcat("object");    }       t+=sizeof(INT32)+1;    /* Prog id */    break;    case T_STRING: my_strcat("string"); break;
pike.git/src/pike_types.c:1347:    push_type(EXTRACT_UCHAR(t2+1));    push_type(T_SCOPE);    }    else if((EXTRACT_UCHAR(t1)==T_STRING && EXTRACT_UCHAR(t2)==T_STRING) ||    (EXTRACT_UCHAR(t1)==T_TYPE && EXTRACT_UCHAR(t2)==T_TYPE) ||    (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)) +  else if(low_pike_types_le(t1, t2, 0))    {    push_unfinished_type(t1);    } -  else if(low_pike_types_le(t2, t1)) +  else if(low_pike_types_le(t2, t1, 0))    {    push_unfinished_type(t2);    }    else    {    push_type(T_ZERO);       if (lower_and_pike_types(t1, t2)) {    /* t1 contains complex types. */    if (low_and_push_complex_pike_type(t2)) {
pike.git/src/pike_types.c:1841:    /* object(* 0) matches any object */    if(!extract_type_int(a+2) || !extract_type_int(b+2)) break;       /* 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) */ -  /* FIXME: Ought to check if a inherits b or b inherits a. */ +     if(extract_type_int(a+2) != extract_type_int(b+2)) return 0;    }else{    /* object(0 *) =? object(0 *) */    /* FIXME: Ought to check the implements relation */    break;    }    }       {    struct program *ap,*bp;
pike.git/src/pike_types.c:1925:    *    * zero    *    * void    *    * Note that non-destructive operations are assumed.    * ie it's assumed that calling a function(mapping(string|int:string|int):void)    * with a mapping(int:int) won't change the type of the mapping after the    * operation.    */ - static int low_pike_types_le(char *a,char *b) + static int low_pike_types_le(char *a, char *b, int array_cnt)   #ifdef PIKE_TYPE_DEBUG   {    int e;    char *s; -  static int low_pike_types_le2(char *a,char *b); +  static int low_pike_types_le2(char *a, char *b, int array_cnt);    int res; -  +  char buf[50];       if (l_flag) {    init_buf();    for(e=0;e<indent;e++) my_strcat(" ");    my_strcat("low_pike_types_le(");    low_describe_type(a);    if(type_length(a) + type_length(b) > 10)    {    my_strcat(",\n");    for(e=0;e<indent;e++) my_strcat(" ");    my_strcat(" ");    low_describe_type(b);    }else{    my_strcat(", ");    low_describe_type(b);    } -  +  if(type_length(a) + type_length(b) > 10) +  { +  my_strcat(",\n"); +  for(e=0;e<indent;e++) my_strcat(" "); +  my_strcat(" "); +  }else{ +  my_strcat(", "); +  } +  sprintf(buf, "%d", array_cnt); +  my_strcat(buf);    my_strcat(");\n");    fprintf(stderr,"%s",(s=simple_free_buf()));    free(s);    indent++;    }    -  res=low_pike_types_le2(a,b); +  res=low_pike_types_le2(a, b, array_cnt);       if (l_flag) {    indent--;       for(e=0;e<indent;e++) fprintf(stderr, " ");    fprintf(stderr, "= %d\n", res);    }    return res;   }    - static int low_pike_types_le2(char *a,char *b) + static int low_pike_types_le2(char *a, char *b, int array_cnt)   #endif /* PIKE_TYPE_DEBUG */      {    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); +  ret = low_pike_types_le(a, b, array_cnt);    if(ret) return ret;    a += type_length(a); -  return low_pike_types_le(a,b); +  return low_pike_types_le(a, b, array_cnt);       case T_OR:    /* OK, if both of the parts are a subset */    a++; -  ret=low_pike_types_le(a,b); +  ret=low_pike_types_le(a, b, array_cnt);    if (!ret) return 0;    a+=type_length(a); -  return low_pike_types_le(a,b); +  return low_pike_types_le(a, b, array_cnt);       case T_NOT: -  return !low_pike_types_le(a+1,b); +  return !low_pike_types_le(a+1, b, array_cnt);       case T_ASSIGN: -  ret=low_pike_types_le(a+2,b); +  ret=low_pike_types_le(a+2, b, array_cnt);    if(ret && EXTRACT_UCHAR(b)!=T_VOID)    {    int m=EXTRACT_UCHAR(a+1)-'0';    struct pike_string *tmp; -  +  int i;    type_stack_mark();    push_unfinished_type_with_markers(b, b_markers); -  +  for(i=array_cnt; i > 0; i--) +  push_type(T_ARRAY);    tmp=pop_unfinished_type();       type_stack_mark();    medium_or_pike_types(a_markers[m], tmp, 0);    if(a_markers[m]) free_string(a_markers[m]);    free_string(tmp);    a_markers[m]=pop_unfinished_type();   #ifdef PIKE_TYPE_DEBUG    if (l_flag) {    char *s;
pike.git/src/pike_types.c:2032:    }   #endif    }    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); +  return low_pike_types_le(a_markers[m]->str, b, array_cnt);    else -  return low_pike_types_le(mixed_type_string->str, b); +  return low_pike_types_le(mixed_type_string->str, b, array_cnt);    }    }       switch(EXTRACT_UCHAR(b))    {    case T_AND:    /* OK, if a is a subset of both parts. */    b++; -  ret = low_pike_types_le(a,b); +  ret = low_pike_types_le(a, b, array_cnt);    if(!ret) return 0;    b+=type_length(b); -  return low_pike_types_le(a,b); +  return low_pike_types_le(a, b, array_cnt);       case T_OR:    /* OK if a is a subset of either of the parts. */    b++; -  ret=low_pike_types_le(a,b); +  ret=low_pike_types_le(a, b, array_cnt);    if (ret) return ret;    b+=type_length(b); -  return low_pike_types_le(a,b); +  return low_pike_types_le(a, b, array_cnt);       case T_NOT: -  return !low_pike_types_le(a,b+1); +  return !low_pike_types_le(a, b+1, array_cnt);       case T_ASSIGN: -  ret=low_pike_types_le(a,b+2); +  ret=low_pike_types_le(a, b+2, array_cnt);    if(ret && EXTRACT_UCHAR(a)!=T_VOID)    {    int m=EXTRACT_UCHAR(b+1)-'0';    struct pike_string *tmp; -  +  int i;    type_stack_mark();    push_unfinished_type_with_markers(a, a_markers); -  +  for(i = array_cnt; i < 0; i++) +  push_type(T_ARRAY);    tmp=pop_unfinished_type();       type_stack_mark();    medium_or_pike_types(b_markers[m], tmp, 0);    if(b_markers[m]) free_string(b_markers[m]);    free_string(tmp);    b_markers[m]=pop_unfinished_type();   #ifdef PIKE_TYPE_DEBUG    if (l_flag) {    char *s;
pike.git/src/pike_types.c:2097:    }   #endif    }    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); +  return low_pike_types_le(a, b_markers[m]->str, array_cnt);    else -  return low_pike_types_le(a, mixed_type_string->str); +  return low_pike_types_le(a, mixed_type_string->str, array_cnt);    } -  +  }    -  case T_MIXED: +  if ((array_cnt < 0) && (EXTRACT_UCHAR(b) == T_ARRAY)) { +  while (EXTRACT_UCHAR(b) == T_ARRAY) { +  b++; +  if (!++array_cnt) break; +  } +  return low_pike_types_le(a, b, array_cnt); +  } else if ((array_cnt > 0) && (EXTRACT_UCHAR(a) == T_ARRAY)) { +  while (EXTRACT_UCHAR(a) == T_ARRAY) { +  a++; +  if (!--array_cnt) break; +  } +  return low_pike_types_le(a, b, array_cnt); +  } +  +  if (EXTRACT_UCHAR(b) == T_MIXED) {    /* any_type <= 'mixed' */ -  +  if (array_cnt <= 0) { +  /* !array(mixed) */    return 1;    } -  +  }       if (EXTRACT_UCHAR(a) == T_MIXED) { -  +  if (array_cnt >= 0) { +  /* !array(mixed) */    return 0;    } -  +  }       if (EXTRACT_UCHAR(a) == T_VOID) {    /* void <= any_type */ -  +  if (array_cnt >= 0) { +  /* !array(void) */    return 1;    } -  +  }       if (EXTRACT_UCHAR(b) == T_VOID) { -  +  if (array_cnt <= 0) { +  /* !array(void) */    return 0;    } -  +  }       if (EXTRACT_UCHAR(a) == T_ZERO) {    /* void <= zero <= any_type */ -  +  if (array_cnt >= 0) { +  /* !array(zero) */    return 1;    } -  +  }       if (EXTRACT_UCHAR(b) == T_ZERO) { -  +  if (array_cnt <= 0) { +  /* !array(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 low_pike_types_le(s->str, b, array_cnt);    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 low_pike_types_le(a, s->str, array_cnt);    return 1;    } -  +  +  case TWOT(T_FUNCTION, T_ARRAY): +  { +  while (EXTRACT_UCHAR(b) == T_ARRAY) { +  b++; +  array_cnt++;    } -  +  return low_pike_types_le(a, b, array_cnt); +  }    -  +  case TWOT(T_ARRAY, T_FUNCTION): +  { +  while (EXTRACT_UCHAR(a) == T_ARRAY) { +  a++; +  array_cnt--; +  } +  return low_pike_types_le(a, b, array_cnt); +  } +  } +     if(EXTRACT_UCHAR(a) != EXTRACT_UCHAR(b)) return 0;    -  switch(EXTRACT_UCHAR(a)) -  { -  case T_FUNCTION: +  if (EXTRACT_UCHAR(a) == T_FUNCTION) {    /*    * function(A...:B) <= function(C...:D) iff C <= A && B <= D    */    /*    * function(:int) <= function(int:int)    * function(int|string:int) <= function(int:int)    * function(:int) <= function(:void)    * function(string:int) != function(int:int)    * function(int:int) != function(:int)    */
pike.git/src/pike_types.c:2192:    if(EXTRACT_UCHAR(b)==T_MANY)    {    b_tmp=b+1;    }else{    b_tmp=b;    b+=type_length(b);    }       if (EXTRACT_UCHAR(a_tmp) != T_VOID) {    /* if (EXTRACT_UCHAR(b_tmp) == T_VOID) return 0; */ -  if (!low_pike_types_le(b_tmp, a_tmp)) return 0; +  if (!low_pike_types_le(b_tmp, a_tmp, 0)) return 0;    }    }    /* check the 'many' type */    a++;    b++;    if (EXTRACT_UCHAR(a) != T_VOID) { -  if (!low_pike_types_le(b, a)) +  if (!low_pike_types_le(b, a, 0))    return 0;    }       a+=type_length(a);    b+=type_length(b);       /* check the returntype */    if (EXTRACT_UCHAR(b) != T_VOID) {    /* FIXME: Check if a has type void here? */ -  if(!low_pike_types_le(a,b)) return 0; +  if(!low_pike_types_le(a, b, array_cnt)) return 0;    } -  break; +  return 1; +  }    -  +  if (array_cnt) return 0; +  +  switch(EXTRACT_UCHAR(a)) +  {    case T_MAPPING:    /*    * mapping(A:B) <= mapping(C:D) iff A <= C && B <= D.    */ -  if(!low_pike_types_le(++a, ++b)) return 0; -  return low_pike_types_le(a+type_length(a),b+type_length(b)); +  if(!low_pike_types_le(++a, ++b, 0)) return 0; +  return low_pike_types_le(a+type_length(a), b+type_length(b), 0);       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|1 x) <= object(0|1 0)    * object(0|1 0) <=! object(0|1 !0)    * object(1 x) <= object(0|1 x) -  * object(1 x) <= object(1 y) iff x inherits y +  * object(1 x) <= object(1 y) iff x == y    * object(0|1 x) <= object(0 y) iff x implements y    */       /* object(* 0) matches any object */    if(!extract_type_int(b+2))    return 1;       if(!extract_type_int(a+2))    return 0;       if ((EXTRACT_UCHAR(a+1) || !EXTRACT_UCHAR(b+1)) &&    (extract_type_int(a+2) == extract_type_int(b+2)))    return 1;       if (EXTRACT_UCHAR(b+1)) { -  if (!EXTRACT_UCHAR(a+1)) { -  /* We can't guarantee the inherit relation. */ +     return 0;    } -  } +        {    struct program *ap = id_to_program(extract_type_int(a+2));    struct program *bp = id_to_program(extract_type_int(b+2));       if (!ap || !bp) {    /* Shouldn't happen... */    return 0;    } -  if (EXTRACT_UCHAR(b+1)) { -  /* FIXME: Should probably have a better test here. */ -  return low_get_storage(ap, bp) != -1; -  } else { +     return implements(ap, bp);    } -  } +     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; +  if(!low_pike_types_le(++a, ++b, 0)) return 0;       case T_FLOAT:    case T_STRING:    case T_TYPE:    case T_PROGRAM:    case T_ZERO:    case T_VOID:    case T_MIXED:    break;   
pike.git/src/pike_types.c:2321:   int strict_check_call(char *fun_type, char *arg_type)   {    while ((EXTRACT_UCHAR(fun_type) == T_OR) ||    (EXTRACT_UCHAR(fun_type) == T_ARRAY)) {    if (EXTRACT_UCHAR(fun_type++) == T_OR) {    int res = strict_check_call(fun_type, arg_type);    if (res) return res;    fun_type += type_length(fun_type);    }    } -  return low_pike_types_le(fun_type, arg_type); +  return low_pike_types_le(fun_type, arg_type, 0);   }      /*    * Return the return type from a function call.    */   static int low_get_return_type(char *a,char *b)   {    int tmp;    switch(EXTRACT_UCHAR(a))    {
pike.git/src/pike_types.c:2381:    if(!tmp) return 0;    push_type(T_ARRAY);    return 1;    }       a=low_match_types(a,b,NO_SHORTCUTS);    if(a)    {   #if 0    if ((lex.pragmas & ID_STRICT_TYPES) && -  !low_pike_types_le(a, b)) { +  !low_pike_types_le(a, b, 0)) {    yywarning("Type mismatch");    }   #endif /* 0 */    switch(EXTRACT_UCHAR(a))    {    case T_FUNCTION:    a++;    while(EXTRACT_UCHAR(a)!=T_MANY) a+=type_length(a);    a++;    a+=type_length(a);
pike.git/src/pike_types.c:2423:    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); +  return low_pike_types_le(a->str, b->str, 0);   }         #ifdef DEBUG_MALLOC   #define low_index_type(X,Y,Z) ((struct pike_string *)debug_malloc_touch(debug_low_index_type((X),(Y),(Z))))   #else   #define low_index_type debug_low_index_type   #endif      /* FIXME, add the index */
pike.git/src/pike_types.c:2864:   {    check_type_string(args);    check_type_string(type);    clear_markers();    type_stack_mark();    max_correct_args=0;       if(low_get_return_type(type->str,args->str))    {    if (lex.pragmas & ID_STRICT_TYPES) { -  if (type == mixed_type_string) { -  yywarning("Calling mixed."); -  } else if (!strict_check_call(type->str, args->str)) { -  struct pike_string *arg_t = describe_type(args); +  if (!strict_check_call(type->str, args->str)) {    struct pike_string *type_t = describe_type(type); -  +  +  if (!low_pike_types_le(type->str, tFunction, 0)) { +  yywarning("Calling non-function value."); +  yywarning("Type called: %s", type_t->str); +  } else { +  struct pike_string *arg_t = describe_type(args);    yywarning("Arguments not strictly compatible.");    yywarning("Expected: %s", type_t->str);    yywarning("Got : %s", arg_t->str); -  free_string(type_t); +     free_string(arg_t);    } -  +  +  free_string(type_t);    } -  +  }    return pop_unfinished_type();    }else{    pop_stack_mark();    return 0;    }   }      INT32 get_max_args(struct pike_string *type)   {    INT32 ret,tmp=max_correct_args;