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.146 2001/02/09 10:29:54 hubbe Exp $"); + RCSID("$Id: pike_types.c,v 1.147 2001/02/19 23:50:02 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:61:    * objects are coded thus:    * T_OBJECT <0/1> <program_id>    * ^    * 0 means 'implements'    * 1 means 'is' (aka 'clone of')    * Integers are encoded as:    * T_INT <min> <max>    * Everything except T_VOID matches T_ZERO.    */    - PMOD_EXPORT struct pike_string *string_type_string; - PMOD_EXPORT struct pike_string *int_type_string; - PMOD_EXPORT struct pike_string *float_type_string; - PMOD_EXPORT struct pike_string *function_type_string; - PMOD_EXPORT struct pike_string *object_type_string; - PMOD_EXPORT struct pike_string *program_type_string; - PMOD_EXPORT struct pike_string *array_type_string; - PMOD_EXPORT struct pike_string *multiset_type_string; - PMOD_EXPORT struct pike_string *mapping_type_string; - PMOD_EXPORT struct pike_string *type_type_string; - PMOD_EXPORT struct pike_string *mixed_type_string; - PMOD_EXPORT struct pike_string *void_type_string; - PMOD_EXPORT struct pike_string *zero_type_string; - PMOD_EXPORT struct pike_string *any_type_string; - PMOD_EXPORT struct pike_string *weak_type_string; /* array|mapping|multiset|function */ + PMOD_EXPORT struct pike_type *string_type_string; + PMOD_EXPORT struct pike_type *int_type_string; + PMOD_EXPORT struct pike_type *float_type_string; + PMOD_EXPORT struct pike_type *function_type_string; + PMOD_EXPORT struct pike_type *object_type_string; + PMOD_EXPORT struct pike_type *program_type_string; + PMOD_EXPORT struct pike_type *array_type_string; + PMOD_EXPORT struct pike_type *multiset_type_string; + PMOD_EXPORT struct pike_type *mapping_type_string; + PMOD_EXPORT struct pike_type *type_type_string; + PMOD_EXPORT struct pike_type *mixed_type_string; + PMOD_EXPORT struct pike_type *void_type_string; + PMOD_EXPORT struct pike_type *zero_type_string; + PMOD_EXPORT struct pike_type *any_type_string; + PMOD_EXPORT struct pike_type *weak_type_string; /* array|mapping|multiset|function */    - static struct pike_string *a_markers[10],*b_markers[10]; + static struct pike_type *a_markers[10],*b_markers[10];      static struct program *implements_a;   static struct program *implements_b;      static void clear_markers(void)   {    unsigned int e;    for(e=0;e<NELEM(a_markers);e++)    {    if(a_markers[e])    { -  free_string(a_markers[e]); +  free_type(a_markers[e]);    a_markers[e]=0;    }    if(b_markers[e])    { -  free_string(b_markers[e]); +  free_type(b_markers[e]);    b_markers[e]=0;    }    }   }      #ifdef PIKE_DEBUG - void check_type_string(struct pike_string *s) + void check_type_string(struct pike_type *s)   {    if(debug_findstring(s) != s)    fatal("Type string not shared.\n");       if(type_length(s->str) != s->len)    {    stupid_describe_type(s->str,s->len);    fatal("Length of type is wrong. (should be %ld, is %ld)\n",    PTRDIFF_T_TO_LONG(type_length(s->str)),    PTRDIFF_T_TO_LONG(s->len));
pike.git/src/pike_types.c:268:   }      void push_unfinished_type(char *s)   {    ptrdiff_t e;    e=type_length(s);    for(e--;e>=0;e--) push_type(s[e]);   }      static void push_unfinished_type_with_markers(char *s, -  struct pike_string **am) +  struct pike_type **am)   {    int d,e,c;    ptrdiff_t len=type_length(s);       type_stack_mark();    for(e=0;e<len;e++)    {    switch(c=EXTRACT_UCHAR(s+e))    {   #if 1
pike.git/src/pike_types.c:316:    for(d=0;d<(int)sizeof(INT32)+1;d++) push_type(EXTRACT_UCHAR(s+ ++e));    break;       default:    push_type(c);    }    }    type_stack_reverse();   }    - void push_finished_type(struct pike_string *type) + void push_finished_type(struct pike_type *type)   {    ptrdiff_t e;    check_type_string(type);    for(e=type->len-1;e>=0;e--) push_type(type->str[e]);   }    - void push_finished_type_backwards(struct pike_string *type) + void push_finished_type_backwards(struct pike_type *type)   {    int e;    check_type_string(type);    MEMCPY(Pike_compiler->type_stackp, type->str, type->len);    Pike_compiler->type_stackp+=type->len;   }    - struct pike_string *debug_pop_unfinished_type(void) + struct pike_type *debug_pop_unfinished_type(void)   {    ptrdiff_t len, e; -  struct pike_string *s; +  struct pike_type *s;    len=pop_stack_mark();    s=begin_shared_string(len);    Pike_compiler->type_stackp-=len;    MEMCPY(s->str, Pike_compiler->type_stackp, len);    reverse(s->str, len, 1);    s=end_shared_string(s);    check_type_string(s);    return s;   }    - struct pike_string *debug_pop_type(void) + struct pike_type *debug_pop_type(void)   { -  struct pike_string *s; +  struct pike_type *s;    s=pop_unfinished_type();    type_stack_mark();    return s;   }    - struct pike_string *debug_compiler_pop_type(void) + struct pike_type *debug_compiler_pop_type(void)   {    if(Pike_compiler->num_parse_error)    {    /* This could be fixed to check if the type    * is correct and then return it, I just didn't feel    * like writing the checking code today. / Hubbe    */    type_stack_pop_to_mark();    type_stack_mark();    reference_shared_string(mixed_type_string);    return mixed_type_string;    }else{ -  struct pike_string *s; +  struct pike_type *s;    s=pop_unfinished_type();    type_stack_mark();    return s;    }   }      static void internal_parse_typeA(char **_s)   {    char buf[80];    unsigned int len;
pike.git/src/pike_types.c:726:    internal_parse_typeC(s);    push_type(T_OR);    }   }      /* This function is used when adding simul efuns so that    * the types for the functions can be easily stored in strings.    * It takes a string on the exact same format as Pike and returns a type    * struct.    */ - struct pike_string *parse_type(char *s) + struct pike_type *parse_type(char *s)   { -  struct pike_string *ret; +  struct pike_type *ret;   #ifdef PIKE_DEBUG    unsigned char *ts=Pike_compiler->type_stackp;    unsigned char **ptms=Pike_compiler->pike_type_mark_stackp;   #endif    type_stack_mark();    internal_parse_type(&s);       if( *s )    fatal("Extra junk at end of type definition.\n");   
pike.git/src/pike_types.c:806: Inside #if defined(PIKE_DEBUG)
   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) + void simple_describe_type(struct pike_type *s)   {    stupid_describe_type(s->str,s->len);   }   #endif      char *low_describe_type(char *t)   {    switch(EXTRACT_UCHAR(t++))    {    case '0': case '1': case '2': case '3': case '4':
pike.git/src/pike_types.c:1033:    my_strcat("unknown code(");    sprintf(buf, "%d", EXTRACT_UCHAR(t-1));    my_strcat(buf);    my_strcat(")");    break;    }    }    return t;   }    - struct pike_string *describe_type(struct pike_string *type) + struct pike_string *describe_type(struct pike_type *type)   {    check_type_string(type);    if(!type) return make_shared_string("mixed");    init_buf();    low_describe_type(type->str);    return free_buf();   }      static int low_is_same_type(char *a, char *b)   {
pike.git/src/pike_types.c:1087:    case T_FUNCTION:       case T_STRING:    case T_TYPE:    case T_INT:    case T_FLOAT:    return EXTRACT_UCHAR(t);    }   }    - TYPE_T compile_type_to_runtime_type(struct pike_string *s) + TYPE_T compile_type_to_runtime_type(struct pike_type *s)   {    return low_compile_type_to_runtime_type(s->str);   }         static int low_find_exact_type_match(char *needle, char *haystack,    int separator)   {    while(EXTRACT_UCHAR(haystack) == separator)    {
pike.git/src/pike_types.c:1193:    push_type(EXTRACT_UCHAR(t2+1));    push_type(T_SCOPE);    }    else    {    push_unfinished_type(t1);    very_low_or_pike_types(t2,t1);    }   }    - static void medium_or_pike_types(struct pike_string *a, -  struct pike_string *b, + static void medium_or_pike_types(struct pike_type *a, +  struct pike_type *b,    int zero_implied)   {    low_or_pike_types( a ? a->str : 0 , b ? b->str : 0 , zero_implied);   }    - struct pike_string *or_pike_types(struct pike_string *a, -  struct pike_string *b, + struct pike_type *or_pike_types(struct pike_type *a, +  struct pike_type *b,    int zero_implied)   {    type_stack_mark();    medium_or_pike_types(a,b,1 /*zero_implied*/);    return pop_unfinished_type();   }      static void very_low_and_pike_types(char *to_push, char *not_push)   {    while(EXTRACT_UCHAR(to_push)==T_AND)
pike.git/src/pike_types.c:1415:    low_and_push_complex_pike_type(t1);    push_type(T_AND);    push_type(T_OR);    }    }    /* push_unfinished_type(t1); */    /* very_low_and_pike_types(t2,t1); */    }   }    - static void medium_and_pike_types(struct pike_string *a, -  struct pike_string *b) + static void medium_and_pike_types(struct pike_type *a, +  struct pike_type *b)   {    low_and_pike_types( a ? a->str : 0 , b ? b->str : 0 );   }    - struct pike_string *and_pike_types(struct pike_string *a, -  struct pike_string *b) + struct pike_type *and_pike_types(struct pike_type *a, +  struct pike_type *b)   {    type_stack_mark();    medium_and_pike_types(a,b);    return pop_unfinished_type();   }    - static struct pike_string *low_object_lfun_type(char *t, short lfun) + static struct pike_type *low_object_lfun_type(char *t, short lfun)   {    struct program *p;    int i;    p=id_to_program(extract_type_int(t+2));    if(!p) return 0;    i=FIND_LFUN(p, lfun);    if(i==-1) return 0;    return ID_FROM_INT(p, i)->type;   }   
pike.git/src/pike_types.c:1574:    case T_NOT:    if(low_match_types(a+1,b,(flags ^ B_EXACT ) | NO_MAX_ARGS))    return 0;    return a;       case T_ASSIGN:    ret=low_match_types(a+2,b,flags);    if(ret && EXTRACT_UCHAR(b)!=T_VOID)    {    int m=EXTRACT_UCHAR(a+1)-'0'; -  struct pike_string *tmp; +  struct pike_type *tmp;    type_stack_mark();    push_unfinished_type_with_markers(b, b_markers);    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); +  if(a_markers[m]) free_type(a_markers[m]); +  free_type(tmp);    a_markers[m]=pop_unfinished_type();      #ifdef PIKE_TYPE_DEBUG    if (l_flag>2) {    char *s;    int e;    init_buf();    for(e=0;e<indent;e++) my_strcat(" ");    my_strcat("a_markers[");    my_putchar((char)(m+'0'));
pike.git/src/pike_types.c:1659:    case T_NOT:    if(low_match_types(a,b+1, (flags ^ A_EXACT ) | NO_MAX_ARGS))    return 0;    return a;       case T_ASSIGN:    ret=low_match_types(a,b+2,flags);    if(ret && EXTRACT_UCHAR(a)!=T_VOID)    {    int m=EXTRACT_UCHAR(b+1)-'0'; -  struct pike_string *tmp; +  struct pike_type *tmp;    type_stack_mark();    push_unfinished_type_with_markers(a, a_markers);    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); +  if(b_markers[m]) free_type(b_markers[m]); +  free_type(tmp);    b_markers[m]=pop_unfinished_type();   #ifdef PIKE_TYPE_DEBUG    if (l_flag>2) {    char *s;    int e;    init_buf();    for(e=0;e<indent;e++) my_strcat(" ");    my_strcat("b_markers[");    my_putchar((char)(m+'0'));    my_strcat("]=");
pike.git/src/pike_types.c:1775:       /* 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; +  struct pike_type *s;    if((s=low_object_lfun_type(a, LFUN_CALL)))    return low_match_types(s->str,b,flags);    if (flags & B_EXACT) {    /* A function isn't an object */    return 0;    }    return a;    }       case TWOT(T_FUNCTION, T_OBJECT):    { -  struct pike_string *s; +  struct pike_type *s;    if((s=low_object_lfun_type(b, LFUN_CALL)))    return low_match_types(a,s->str,flags);    if (flags & A_EXACT) {    /* A function isn't an object */    return 0;    }    return a;    }    }   
pike.git/src/pike_types.c:2086:    return 0;    }    /* FIXME: This is wrong... */    return !low_pike_types_le(b, a+1, -array_cnt, flags);       case T_ASSIGN:    ret=low_pike_types_le(a+2, b, array_cnt, flags);    if(ret && EXTRACT_UCHAR(b)!=T_VOID)    {    int m=EXTRACT_UCHAR(a+1)-'0'; -  struct pike_string *tmp; +  struct pike_type *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); +  if(a_markers[m]) free_type(a_markers[m]); +  free_type(tmp);    a_markers[m]=pop_unfinished_type();   #ifdef PIKE_TYPE_DEBUG    if (l_flag>2) {    char *s;    int e;    init_buf();    for(e=0;e<indent;e++) my_strcat(" ");    my_strcat("a_markers[");    my_putchar((char)(m+'0'));    my_strcat("]=");
pike.git/src/pike_types.c:2161:    return 0;    }    /* FIXME: This is wrong... */    return !low_pike_types_le(b+1, a, -array_cnt, flags);       case T_ASSIGN:    ret=low_pike_types_le(a, b+2, array_cnt, flags);    if(ret && EXTRACT_UCHAR(a)!=T_VOID)    {    int m=EXTRACT_UCHAR(b+1)-'0'; -  struct pike_string *tmp; +  struct pike_type *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); +  if(b_markers[m]) free_type(b_markers[m]); +  free_type(tmp);    b_markers[m]=pop_unfinished_type();   #ifdef PIKE_TYPE_DEBUG    if (l_flag>2) {    char *s;    int e;    init_buf();    for(e=0;e<indent;e++) my_strcat(" ");    my_strcat("b_markers[");    my_putchar((char)(m+'0'));    my_strcat("]=");
pike.git/src/pike_types.c:2276:    /* 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; +  struct pike_type *s;    if((s=low_object_lfun_type(a, LFUN_CALL)))    return low_pike_types_le(s->str, b, array_cnt, flags);    return 1;    }       case TWOT(T_FUNCTION, T_OBJECT):    { -  struct pike_string *s; +  struct pike_type *s;    if((s=low_object_lfun_type(b, LFUN_CALL)))    return low_pike_types_le(a, s->str, array_cnt, flags);    return 1;    }       case TWOT(T_FUNCTION, T_ARRAY):    {    while (EXTRACT_UCHAR(b) == T_ARRAY) {    b++;    array_cnt++;
pike.git/src/pike_types.c:2490:    }    }    return low_pike_types_le(fun_type, arg_type, 0, 0);   }      /*    * Check validity of soft-cast.    * Note: This uses a weaker check of function arguments, since    * people get confused otherwise.    */ - int check_soft_cast(struct pike_string *to, struct pike_string *from) + int check_soft_cast(struct pike_type *to, struct pike_type *from)   {    return low_pike_types_le(to->str, from->str, 0, LE_WEAK_OBJECTS);   }      /*    * 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; +  struct pike_type *o1, *o2;    a++;    o1=o2=0;       type_stack_mark();    if(low_get_return_type(a,b))    {    o1=pop_unfinished_type();    type_stack_mark();    }       if(low_get_return_type(a+type_length(a),b))    o2=pop_unfinished_type();    else    pop_stack_mark();       if(!o1 && !o2) return 0;       medium_or_pike_types(o1,o2, 0);    -  if(o1) free_string(o1); -  if(o2) free_string(o2); +  if(o1) free_type(o1); +  if(o2) free_type(o2);       return 1;    }       case T_AND:    a++;    type_stack_mark();    tmp=low_get_return_type(a,b);    type_stack_pop_to_mark();    if(!tmp) return 0;
pike.git/src/pike_types.c:2581:       default:    push_type(T_MIXED);    return 1;    }    }    return 0;   }       - int match_types(struct pike_string *a,struct pike_string *b) + int match_types(struct pike_type *a, struct pike_type *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) + int pike_types_le(struct pike_type *a, struct pike_type *b)   {    check_type_string(a);    check_type_string(b);    clear_markers();    return low_pike_types_le(a->str, b->str, 0, 0);   }         #ifdef DEBUG_MALLOC - #define low_index_type(X,Y,Z) ((struct pike_string *)debug_malloc_pass(debug_low_index_type((X),(Y),(Z)))) + #define low_index_type(X,Y,Z) ((struct pike_type *)debug_malloc_pass(debug_low_index_type((X),(Y),(Z))))   #else   #define low_index_type debug_low_index_type   #endif      /* FIXME, add the index */ - static struct pike_string *debug_low_index_type(char *t, + static struct pike_type *debug_low_index_type(char *t,    char *index_type,    node *n)   { -  struct pike_string *tmp; +  struct pike_type *tmp;    struct program *p;       switch(low_check_indexing(t, index_type, n))    {    case 0: return 0;    case -1:    reference_shared_string(zero_type_string);    return zero_type_string;    }   
pike.git/src/pike_types.c:2715:    goto comefrom_int_index;   #endif    case T_ZERO:    case T_TYPE:    case T_VOID:    case T_FLOAT:    return 0;       case T_OR:    { -  struct pike_string *a,*b; +  struct pike_type *a, *b;    a=low_index_type(t,index_type,n);    t+=type_length(t);    b=low_index_type(t,index_type,n);    if(!b) return a;    if(!a) return b;    type_stack_mark();    medium_or_pike_types(a,b,1); -  free_string(a); -  free_string(b); +  free_type(a); +  free_type(b);    return pop_unfinished_type();    }       case T_AND:    return low_index_type(t+type_length(t),index_type,n);       case T_STRING: /* always int */    case T_MULTISET: /* always int */    reference_shared_string(int_type_string);    return int_type_string;       case T_MAPPING:    t+=type_length(t);    return make_shared_binary_string(t, type_length(t));       case T_ARRAY:    { -  struct pike_string *a; +  struct pike_type *a;       if(low_pike_types_le(tString, index_type, 0, 0) &&    (a = low_index_type(t, tString, n))) {    /* Possible to index the array with a string. */    type_stack_mark();    push_finished_type(a); -  free_string(a); +  free_type(a);    push_type(T_ARRAY);       if (low_match_types(tInt, index_type, 0)) {    /* Also possible to index the array with an int. */    push_unfinished_type(t);    push_type(T_OR);    }    return pop_unfinished_type();    }    if (low_match_types(tInt, index_type, 0)) {    /* Possible to index the array with an int. */    return make_shared_binary_string(t, type_length(t));    }    /* Bad index type. */    return 0;    }    }   }    - struct pike_string *index_type(struct pike_string *type, -  struct pike_string *index_type, + struct pike_type *index_type(struct pike_type *type, +  struct pike_type *index_type,    node *n)   { -  struct pike_string *t; +  struct pike_type *t;    clear_markers();    t=low_index_type(type->str,index_type->str,n);    if(!t) copy_shared_string(t,mixed_type_string);    return t;   }       - static struct pike_string *low_array_value_type(char *arr_t) + static struct pike_type *low_array_value_type(char *arr_t)   { -  struct pike_string *res = NULL; -  struct pike_string *sub_t; +  struct pike_type *res = NULL; +  struct pike_type *sub_t;       while (EXTRACT_UCHAR(arr_t) == T_OR) {    arr_t++;    sub_t = low_array_value_type(arr_t);    arr_t += type_length(arr_t);    if (sub_t) {    if (res) { -  struct pike_string *new = or_pike_types(res, sub_t, 1); -  free_string(res); -  free_string(sub_t); +  struct pike_type *new = or_pike_types(res, sub_t, 1); +  free_type(res); +  free_type(sub_t);    res = new;    } else {    res = sub_t;    }    }    }    if (EXTRACT_UCHAR(arr_t) != T_ARRAY)    return res;    arr_t++;    sub_t = make_shared_binary_string(arr_t, type_length(arr_t));    if (res) { -  struct pike_string *new = or_pike_types(res, sub_t, 1); -  free_string(res); -  free_string(sub_t); +  struct pike_type *new = or_pike_types(res, sub_t, 1); +  free_type(res); +  free_type(sub_t);    return new;    }    return sub_t;   }    - struct pike_string *array_value_type(struct pike_string *array_type) + struct pike_type *array_value_type(struct pike_type *array_type)   { -  struct pike_string *t = low_array_value_type(array_type->str); +  struct pike_type *t = low_array_value_type(array_type->str);    if (!t) copy_shared_string(t, mixed_type_string);    return t;   }         #ifdef DEBUG_MALLOC - #define low_key_type(X,Y) ((struct pike_string *)debug_malloc_pass(debug_low_key_type((X),(Y)))) + #define low_key_type(X,Y) ((struct pike_type *)debug_malloc_pass(debug_low_key_type((X),(Y))))   #else   #define low_key_type debug_low_key_type   #endif      /* FIXME, add the index */ - static struct pike_string *debug_low_key_type(char *t, node *n) + static struct pike_type *debug_low_key_type(char *t, node *n)   {    switch(EXTRACT_UCHAR(t++))    {    case T_OBJECT:    {    struct program *p=id_to_program(extract_type_int(t+1));    if(p && n)    {    if(n->token == F_ARROW)    {
pike.git/src/pike_types.c:2869:       case T_VOID:    case T_ZERO:    case T_TYPE:    case T_FLOAT:    case T_INT:    return 0;       case T_OR:    { -  struct pike_string *a,*b; +  struct pike_type *a, *b;    a=low_key_type(t,n);    t+=type_length(t);    b=low_key_type(t,n);    if(!b) return a;    if(!a) return b;    type_stack_mark();    medium_or_pike_types(a,b,1); -  free_string(a); -  free_string(b); +  free_type(a); +  free_type(b);    return pop_unfinished_type();    }       case T_AND:    return low_key_type(t+type_length(t),n);       case T_ARRAY:    case T_STRING: /* always int */    reference_shared_string(int_type_string);    return int_type_string;       case T_MAPPING:    case T_MULTISET:    return make_shared_binary_string(t, type_length(t));    }   }    - struct pike_string *key_type(struct pike_string *type, node *n) + struct pike_type *key_type(struct pike_type *type, node *n)   { -  struct pike_string *t; +  struct pike_type *t;    clear_markers();    t=low_key_type(type->str,n);    if(!t) copy_shared_string(t,mixed_type_string);    return t;   }            static int low_check_indexing(char *type, char *index_type, node *n)   {
pike.git/src/pike_types.c:2967:    return !!low_match_types(string_type_string->str, index_type,0);       case T_MIXED:    return 1;       default:    return 0;    }   }    - int check_indexing(struct pike_string *type, -  struct pike_string *index_type, + int check_indexing(struct pike_type *type, +  struct pike_type *index_type,    node *n)   {    check_type_string(type);    check_type_string(index_type);       return low_check_indexing(type->str, index_type->str, n);   }      static int low_count_arguments(char *q)   {
pike.git/src/pike_types.c:3018:    q++;    if(EXTRACT_UCHAR(q)!=T_VOID) return ~num;    return num;    }   }      /* Count the number of arguments for a funciton type.    * return -1-n if the function can take number of arguments    * >= n (varargs)    */ - int count_arguments(struct pike_string *s) + int count_arguments(struct pike_type *s)   {    check_type_string(s);       return low_count_arguments(s->str);   }         static int low_minimum_arguments(char *q)   {    int num;
pike.git/src/pike_types.c:3055:       num++;    q+=type_length(q);    }    return num;    }   }      /* Count the minimum number of arguments for a funciton type.    */ - int minimum_arguments(struct pike_string *s) + int minimum_arguments(struct pike_type *s)   {    int ret;    check_type_string(s);       ret=low_minimum_arguments(s->str);      #if 0    fprintf(stderr,"minimum_arguments(");    simple_describe_type(s);    fprintf(stderr," ) -> %d\n",ret);   #endif       return ret;   }    - struct pike_string *check_call(struct pike_string *args, -  struct pike_string *type, + struct pike_type *check_call(struct pike_type *args, +  struct pike_type *type,    int strict)   {    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))    {
pike.git/src/pike_types.c:3108:    free_string(type_t);    }    }    return pop_unfinished_type();    }else{    pop_stack_mark();    return 0;    }   }    - INT32 get_max_args(struct pike_string *type) + INT32 get_max_args(struct pike_type *type)   {    INT32 ret,tmp=max_correct_args;    check_type_string(type);    clear_markers();    type = check_call(function_type_string, type, 0); -  if(type) free_string(type); +  if(type) free_type(type);    ret=max_correct_args;    max_correct_args=tmp;    return tmp;   }       - struct pike_string *zzap_function_return(char *a, INT32 id) + struct pike_type *zzap_function_return(char *a, INT32 id)   {    switch(EXTRACT_UCHAR(a))    {    case T_OR:    { -  struct pike_string *ar, *br, *ret=0; +  struct pike_type *ar, *br, *ret=0;    a++;    ar=zzap_function_return(a,id);    br=zzap_function_return(a+type_length(a),id);    if(ar && br) ret=or_pike_types(ar,br,0); -  if(ar) free_string(ar); -  if(br) free_string(br); +  if(ar) free_type(ar); +  if(br) free_type(br);    return ret;    }       case T_FUNCTION:    type_stack_mark();    push_type_int(id);    push_type(1);    push_type(T_OBJECT);       type_stack_mark();
pike.git/src/pike_types.c:3175:    /* I wonder when this occurrs, but apparently it does... */    return zzap_function_return(tFuncV(tVoid,tOr(tMix,tVoid),tObj), id);    }   /* This error is bogus /Hubbe    fatal("zzap_function_return() called with unexpected value: %d\n",    EXTRACT_UCHAR(a));   */    return NULL;   }    - struct pike_string *get_type_of_svalue(struct svalue *s) + struct pike_type *get_type_of_svalue(struct svalue *s)   { -  struct pike_string *ret; +  struct pike_type *ret;    switch(s->type)    {    case T_FUNCTION:    if(s->subtype == FUNCTION_BUILTIN)    {    ret=s->u.efun->type;    }else{    struct program *p;       p=s->u.object->prog;
pike.git/src/pike_types.c:3201:    }else{    ret=ID_FROM_INT(p,s->subtype)->type;    }    }    reference_shared_string(ret);    return ret;       case T_MULTISET:    case T_ARRAY:    { -  struct pike_string *arg_type; +  struct pike_type *arg_type;    struct array *a;       if (s->type == T_MULTISET) {    a = s->u.multiset->ind;    } else {    a = s->u.array;    }   #if 0    int i;       /* FIXME: Circular structures? */    copy_shared_string(arg_type, zero_type_string);    for (i = 0; i < a->size; i++) { -  struct pike_string *tmp1 = get_type_of_svalue(a->item+i); -  struct pike_string *tmp2 = or_pike_types(arg_type, tmp1, 1); -  free_string(arg_type); -  free_string(tmp1); +  struct pike_type *tmp1 = get_type_of_svalue(a->item+i); +  struct pike_type *tmp2 = or_pike_types(arg_type, tmp1, 1); +  free_type(arg_type); +  free_type(tmp1);    arg_type = tmp2;    }   #else /* !0 */    if (a->size)    copy_shared_string(arg_type, mixed_type_string);    else    copy_shared_string(arg_type, zero_type_string);   #endif /* 0 */    type_stack_mark();    push_unfinished_type(arg_type->str); -  free_string(arg_type); +  free_type(arg_type);    push_type(s->type);    return pop_unfinished_type();    }          case T_MAPPING:    type_stack_mark();    if (m_sizeof(s->u.mapping)) {    push_type(T_MIXED);    push_type(T_MIXED);
pike.git/src/pike_types.c:3291:    return pop_unfinished_type();    }else{    ret=zero_type_string;    }    reference_shared_string(ret);    return ret;       case T_PROGRAM:    {    char *a; -  struct pike_string *tmp; +  struct pike_type *tmp;    int id;       if(s->u.program->identifiers)    {    id=FIND_LFUN(s->u.program,LFUN_CREATE);    if(id>=0)    {    a=ID_FROM_INT(s->u.program, id)->type->str;    if((tmp=zzap_function_return(a, s->u.program->id)))    return tmp;
pike.git/src/pike_types.c:3326:    fatal("Completely failed to zzap function return!\n");    }       default:    type_stack_mark();    push_type(s->type);    return pop_unfinished_type();    }   }    - static struct pike_string *low_object_type_to_program_type(char *obj_t) + static struct pike_type *low_object_type_to_program_type(char *obj_t)   { -  struct pike_string *res = NULL; -  struct pike_string *sub; +  struct pike_type *res = NULL; +  struct pike_type *sub;    struct svalue sval;    int id;       while(EXTRACT_UCHAR(obj_t) == T_OR) {    obj_t++;    sub = low_object_type_to_program_type(obj_t);    if (!sub) {    if (res) { -  free_string(res); +  free_type(res);    }    return NULL;    }    if (res) { -  struct pike_string *tmp = or_pike_types(res, sub, 1); -  free_string(res); -  free_string(sub); +  struct pike_type *tmp = or_pike_types(res, sub, 1); +  free_type(res); +  free_type(sub);    res = tmp;    } else {    res = sub;    }    obj_t += type_length(obj_t);    }    sval.type = T_PROGRAM;    if ((EXTRACT_UCHAR(obj_t) != T_OBJECT) ||    (!(id = extract_type_int(obj_t + 2))) ||    (!(sval.u.program = id_to_program(id))) ||    (!(sub = get_type_of_svalue(&sval)))) {    if (res) { -  free_string(res); +  free_type(res);    }    return NULL;    }    /* FIXME: obj_t + 1 should propagate to the return-type in sub. */    if (res) { -  struct pike_string *tmp = or_pike_types(res, sub, 1); -  free_string(res); -  free_string(sub); +  struct pike_type *tmp = or_pike_types(res, sub, 1); +  free_type(res); +  free_type(sub);    return tmp;    }    return sub;   }      /* Used by fix_object_program_type() */ - struct pike_string *object_type_to_program_type(struct pike_string *obj_t) + struct pike_type *object_type_to_program_type(struct pike_type *obj_t)   {    return low_object_type_to_program_type(obj_t->str);   }      char *get_name_of_type(int t)   {    switch(t)    {    case T_ARRAY: return "array";    case T_FLOAT: return "float";
pike.git/src/pike_types.c:3402:    case T_TYPE: return "type";    case T_ZERO: return "zero";    case T_VOID: return "void";    case T_MAPPING_DATA: return "mapping_data";    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(type_type_string); -  free_string(mixed_type_string); -  free_string(void_type_string); -  free_string(zero_type_string); -  free_string(any_type_string); -  free_string(weak_type_string); +  free_type(string_type_string); +  free_type(int_type_string); +  free_type(float_type_string); +  free_type(function_type_string); +  free_type(object_type_string); +  free_type(program_type_string); +  free_type(array_type_string); +  free_type(multiset_type_string); +  free_type(mapping_type_string); +  free_type(type_type_string); +  free_type(mixed_type_string); +  free_type(void_type_string); +  free_type(zero_type_string); +  free_type(any_type_string); +  free_type(weak_type_string);   }         int type_may_overload(char *type, int lfun)   {    switch(EXTRACT_UCHAR(type++))    {    case T_ASSIGN:    return type_may_overload(type+1,lfun);   
pike.git/src/pike_types.c:3458:    case T_OBJECT:    {    struct program *p=id_to_program(extract_type_int(type+1));    if(!p) return 1;    return FIND_LFUN(p, lfun)!=-1;    }    }   }       - void yyexplain_nonmatching_types(struct pike_string *type_a, -  struct pike_string *type_b, + void yyexplain_nonmatching_types(struct pike_type *type_a, +  struct pike_type *type_b,    int flags)   {    implements_a=0;    implements_b=0;       match_types(type_a,type_b);      #if 0    if(!(implements_a && implements_b &&    type_a->str[0]==T_OBJECT &&
pike.git/src/pike_types.c:3493:    }    free_string(s1);    free_string(s2);    }       if(implements_a && implements_b)    yyexplain_not_implements(implements_a,implements_b,flags);   }       - struct pike_string *make_pike_type(char *t) + struct pike_type *make_pike_type(char *t)   {    return make_shared_binary_string(t, type_length(t));   }         int pike_type_allow_premature_toss(char *type)   {    again:    switch(EXTRACT_UCHAR(type++))    {
pike.git/src/pike_types.c:3532:    case T_ARRAY:    case T_MULTISET:    goto again;       case T_PROGRAM:    case T_INT:    case T_FLOAT:    case T_STRING:    return 1;    } +  /* NOT_REACHED */ +  return 0;   }