1999-11-23
1999-11-23 22:35:44 by Henrik Grubbström (Grubba) <grubba@grubba.org>
-
93dd41e408b799f3d44f7b9cdd00b8035cc91f38
(365 lines)
(+348/-17)
[
Show
| Annotate
]
Branch: 7.9
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);
}