mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Changes so that user-defined classes can implement operations invoked
by special syntax: you can now define your own numbers, sequences and mappings.
This commit is contained in:
		
							parent
							
								
									423d6c6bca
								
							
						
					
					
						commit
						04691fc1c1
					
				
					 5 changed files with 609 additions and 42 deletions
				
			
		|  | @ -77,13 +77,13 @@ void flushline PROTO((void)); | |||
| */ | ||||
| 
 | ||||
| extern void init_save_thread PROTO((void)); | ||||
| extern void *save_thread PROTO((void)); | ||||
| extern void restore_thread PROTO((void *)); | ||||
| extern object *save_thread PROTO((void)); | ||||
| extern void restore_thread PROTO((object *)); | ||||
| 
 | ||||
| #ifdef USE_THREAD | ||||
| 
 | ||||
| #define BGN_SAVE { \ | ||||
| 			void *_save; \ | ||||
| 			object *_save; \ | ||||
| 			_save = save_thread(); | ||||
| #define RET_SAVE	restore_thread(_save); | ||||
| #define RES_SAVE	_save = save_thread(); | ||||
|  |  | |||
|  | @ -42,3 +42,6 @@ extern object *newinstancemethodobject PROTO((object *, object *)); | |||
| 
 | ||||
| extern object *instancemethodgetfunc PROTO((object *)); | ||||
| extern object *instancemethodgetself PROTO((object *)); | ||||
| 
 | ||||
| extern int instance_coerce PROTO((object **, object **)); | ||||
| extern object *instance_convert PROTO((object *, char *)); | ||||
|  |  | |||
|  | @ -25,8 +25,12 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| /* Class object implementation */ | ||||
| 
 | ||||
| #include "allobjects.h" | ||||
| 
 | ||||
| #include "modsupport.h" | ||||
| #include "structmember.h" | ||||
| #include "ceval.h" | ||||
| 
 | ||||
| extern typeobject MappingInstancetype; | ||||
| extern typeobject SequenceInstancetype; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	OB_HEAD | ||||
|  | @ -166,6 +170,7 @@ newinstanceobject(class) | |||
| 	register object *class; | ||||
| { | ||||
| 	register instanceobject *inst; | ||||
| 	object *v; | ||||
| 	if (!is_classobject(class)) { | ||||
| 		err_badcall(); | ||||
| 		return NULL; | ||||
|  | @ -246,6 +251,428 @@ instance_setattr(inst, name, v) | |||
| 		return dictinsert(inst->in_attr, name, v); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| instance_print(inst, fp, flags) | ||||
| 	instanceobject *inst; | ||||
| 	FILE *fp; | ||||
| 	int flags; | ||||
| { | ||||
| 	object *func, *repr; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__repr__"); | ||||
| 	if (func == NULL) { | ||||
| 		err_clear(); | ||||
| 		fprintf(fp, "<instance object at %lx>", (long)inst); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	repr = call_object(func, (object *)NULL); | ||||
| 	DECREF(func); | ||||
| 	if (repr == NULL) | ||||
| 		return -1; | ||||
| 	ret = printobject(repr, fp, flags | PRINT_RAW); | ||||
| 	DECREF(repr); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| object * | ||||
| instance_repr(inst) | ||||
| 	instanceobject *inst; | ||||
| { | ||||
| 	object *func; | ||||
| 	object *res; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__repr__"); | ||||
| 	if (func == NULL) { | ||||
| 		char buf[80]; | ||||
| 		err_clear(); | ||||
| 		sprintf(buf, "<instance object at %lx>", (long)inst); | ||||
| 		return newstringobject(buf); | ||||
| 	} | ||||
| 	res = call_object(func, (object *)NULL); | ||||
| 	DECREF(func); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| instance_compare(inst, other) | ||||
| 	instanceobject *inst, *other; | ||||
| { | ||||
| 	object *func; | ||||
| 	object *res; | ||||
| 	int outcome; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__cmp__"); | ||||
| 	if (func == NULL) { | ||||
| 		err_clear(); | ||||
| 		if (inst < other) | ||||
| 			return -1; | ||||
| 		if (inst > other) | ||||
| 			return 1; | ||||
| 		return 0; | ||||
| 	} | ||||
| 	res = call_object(func, (object *)other); | ||||
| 	DECREF(func); | ||||
| 	if (res == NULL) { | ||||
| 		err_clear(); /* XXX Should report the error, bot how...??? */ | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (is_intobject(res)) | ||||
| 		outcome = getintvalue(res); | ||||
| 	else | ||||
| 		outcome = 0; /* XXX Should report the error, bot how...??? */ | ||||
| 	DECREF(res); | ||||
| 	return outcome; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| instance_length(inst) | ||||
| 	instanceobject *inst; | ||||
| { | ||||
| 	object *func; | ||||
| 	object *res; | ||||
| 	int outcome; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__len__"); | ||||
| 	if (func == NULL) | ||||
| 		return -1; | ||||
| 	res = call_object(func, (object *)NULL); | ||||
| 	DECREF(func); | ||||
| 	if (is_intobject(res)) { | ||||
| 		outcome = getintvalue(res); | ||||
| 		if (outcome < 0) | ||||
| 			err_setstr(ValueError, "__len__() should return >= 0"); | ||||
| 	} | ||||
| 	else { | ||||
| 		err_setstr(TypeError, "__len__() should return an int"); | ||||
| 		outcome = -1; | ||||
| 	} | ||||
| 	DECREF(res); | ||||
| 	return outcome; | ||||
| } | ||||
| 
 | ||||
| object * | ||||
| instance_subscript(inst, key) | ||||
| 	instanceobject *inst; | ||||
| 	object *key; | ||||
| { | ||||
| 	object *func; | ||||
| 	object *arg; | ||||
| 	object *res; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__getitem__"); | ||||
| 	if (func == NULL) | ||||
| 		return NULL; | ||||
| 	arg = mkvalue("(O)", key); | ||||
| 	if (arg == NULL) { | ||||
| 		DECREF(func); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	res = call_object(func, arg); | ||||
| 	DECREF(func); | ||||
| 	DECREF(arg); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| instance_ass_subscript(inst, key, value) | ||||
| 	instanceobject*inst; | ||||
| 	object *key; | ||||
| 	object *value; | ||||
| { | ||||
| 	object *func; | ||||
| 	object *arg; | ||||
| 	object *res; | ||||
| 
 | ||||
| 	if (value == NULL) | ||||
| 		func = instance_getattr(inst, "__delitem__"); | ||||
| 	else | ||||
| 		func = instance_getattr(inst, "__setitem__"); | ||||
| 	if (func == NULL) | ||||
| 		return -1; | ||||
| 	if (value == NULL) | ||||
| 		arg = mkvalue("(O)", key); | ||||
| 	else | ||||
| 		arg = mkvalue("(OO)", key, value); | ||||
| 	if (arg == NULL) { | ||||
| 		DECREF(func); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	res = call_object(func, arg); | ||||
| 	DECREF(func); | ||||
| 	DECREF(arg); | ||||
| 	if (res == NULL) | ||||
| 		return -1; | ||||
| 	DECREF(res); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| mapping_methods instance_as_mapping = { | ||||
| 	instance_length,	/*mp_length*/ | ||||
| 	instance_subscript,	/*mp_subscript*/ | ||||
| 	instance_ass_subscript,	/*mp_ass_subscript*/ | ||||
| }; | ||||
| 
 | ||||
| static object * | ||||
| instance_concat(inst, other) | ||||
| 	instanceobject *inst, *other; | ||||
| { | ||||
| 	object *func, *res; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__add__"); | ||||
| 	if (func == NULL) | ||||
| 		return NULL; | ||||
| 	res = call_object(func, (object *)other); | ||||
| 	DECREF(func); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
| instance_repeat(inst, count) | ||||
| 	instanceobject *inst; | ||||
| 	int count; | ||||
| { | ||||
| 	object *func, *arg, *res; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__mul__"); | ||||
| 	if (func == NULL) | ||||
| 		return NULL; | ||||
| 	arg = newintobject((long)count); | ||||
| 	if (arg == NULL) { | ||||
| 		DECREF(func); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	res = call_object(func, arg); | ||||
| 	DECREF(func); | ||||
| 	DECREF(arg); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
| instance_item(inst, i) | ||||
| 	instanceobject *inst; | ||||
| 	int i; | ||||
| { | ||||
| 	object *func, *arg, *res; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__getitem__"); | ||||
| 	if (func == NULL) | ||||
| 		return NULL; | ||||
| 	arg = newintobject((long)i); | ||||
| 	if (arg == NULL) { | ||||
| 		DECREF(func); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	res = call_object(func, arg); | ||||
| 	DECREF(func); | ||||
| 	DECREF(arg); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
| instance_slice(inst, i, j) | ||||
| 	instanceobject *inst; | ||||
| 	int i, j; | ||||
| { | ||||
| 	object *func, *arg, *res; | ||||
| 
 | ||||
| 	func = instance_getattr(inst, "__getslice__"); | ||||
| 	if (func == NULL) | ||||
| 		return NULL; | ||||
| 	arg = mkvalue("(ii)", i, j); | ||||
| 	if (arg == NULL) { | ||||
| 		DECREF(func); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	res = call_object(func, arg); | ||||
| 	DECREF(func); | ||||
| 	DECREF(arg); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| instance_ass_item(inst, i, item) | ||||
| 	instanceobject *inst; | ||||
| 	int i; | ||||
| 	object *item; | ||||
| { | ||||
| 	object *func, *arg, *res; | ||||
| 
 | ||||
| 	if (item == NULL) | ||||
| 		func = instance_getattr(inst, "__delitem__"); | ||||
| 	else | ||||
| 		func = instance_getattr(inst, "__setitem__"); | ||||
| 	if (func == NULL) | ||||
| 		return NULL; | ||||
| 	if (item == NULL) | ||||
| 		arg = mkvalue("i", i); | ||||
| 	else | ||||
| 		arg = mkvalue("(iO)", i, item); | ||||
| 	if (arg == NULL) { | ||||
| 		DECREF(func); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	res = call_object(func, arg); | ||||
| 	DECREF(func); | ||||
| 	DECREF(arg); | ||||
| 	if (res == NULL) | ||||
| 		return -1; | ||||
| 	DECREF(res); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| instance_ass_slice(inst, i, j, value) | ||||
| 	instanceobject *inst; | ||||
| 	int i, j; | ||||
| 	object *value; | ||||
| { | ||||
| 	object *func, *arg, *res; | ||||
| 
 | ||||
| 	if (value == NULL) | ||||
| 		func = instance_getattr(inst, "__delslice__"); | ||||
| 	else | ||||
| 		func = instance_getattr(inst, "__setslice__"); | ||||
| 	if (func == NULL) | ||||
| 		return NULL; | ||||
| 	if (value == NULL) | ||||
| 		arg = mkvalue("(ii)", i, j); | ||||
| 	else | ||||
| 		arg = mkvalue("(iiO)", i, j, value); | ||||
| 	if (arg == NULL) { | ||||
| 		DECREF(func); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	res = call_object(func, arg); | ||||
| 	DECREF(func); | ||||
| 	DECREF(arg); | ||||
| 	if (res == NULL) | ||||
| 		return -1; | ||||
| 	DECREF(res); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static sequence_methods instance_as_sequence = { | ||||
| 	instance_length,	/*sq_length*/ | ||||
| 	instance_concat,	/*sq_concat*/ | ||||
| 	instance_repeat,	/*sq_repeat*/ | ||||
| 	instance_item,		/*sq_item*/ | ||||
| 	instance_slice,		/*sq_slice*/ | ||||
| 	instance_ass_item,	/*sq_ass_item*/ | ||||
| 	instance_ass_slice,	/*sq_ass_slice*/ | ||||
| }; | ||||
| 
 | ||||
| static object * | ||||
| generic_binary_op(self, other, methodname) | ||||
| 	instanceobject *self; | ||||
| 	object *other; | ||||
| 	char *methodname; | ||||
| { | ||||
| 	object *func, *res; | ||||
| 
 | ||||
| 	if ((func = instance_getattr(self, methodname)) == NULL) | ||||
| 		return NULL; | ||||
| 	res = call_object(func, other); | ||||
| 	DECREF(func); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
| generic_unary_op(self, methodname) | ||||
| 	instanceobject *self; | ||||
| 	char *methodname; | ||||
| { | ||||
| 	object *func, *res; | ||||
| 
 | ||||
| 	if ((func = instance_getattr(self, methodname)) == NULL) | ||||
| 		return NULL; | ||||
| 	res = call_object(func, (object *)NULL); | ||||
| 	DECREF(func); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| #define BINARY(funcname, methodname) \ | ||||
| static object * funcname(self, other) instanceobject *self; object *other; { \ | ||||
| 	return generic_binary_op(self, other, methodname); \ | ||||
| } | ||||
| 
 | ||||
| #define UNARY(funcname, methodname) \ | ||||
| static object *funcname(self) instanceobject *self; { \ | ||||
| 	return generic_unary_op(self, methodname); \ | ||||
| } | ||||
| 
 | ||||
| BINARY(instance_add, "__add__") | ||||
| BINARY(instance_sub, "__sub__") | ||||
| BINARY(instance_mul, "__mul__") | ||||
| BINARY(instance_div, "__div__") | ||||
| BINARY(instance_mod, "__mod__") | ||||
| BINARY(instance_divmod, "__divmod__") | ||||
| BINARY(instance_pow, "__pow__") | ||||
| UNARY(instance_neg, "__neg__") | ||||
| UNARY(instance_pos, "__pos__") | ||||
| UNARY(instance_abs, "__abs__") | ||||
| 
 | ||||
| int | ||||
| instance_nonzero(self) | ||||
| 	instanceobject *self; | ||||
| { | ||||
| 	object *func, *res; | ||||
| 	long outcome; | ||||
| 
 | ||||
| 	if ((func = instance_getattr(self, "__len__")) == NULL) { | ||||
| 		err_clear(); | ||||
| 		if ((func = instance_getattr(self, "__nonzero__")) == NULL) { | ||||
| 			err_clear(); | ||||
| 			/* Fall back to the default behavior:
 | ||||
| 			   all instances are nonzero */ | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 	res = call_object(func, (object *)NULL); | ||||
| 	DECREF(func); | ||||
| 	if (res == NULL) | ||||
| 		return -1; | ||||
| 	if (!is_intobject(res)) { | ||||
| 		DECREF(res); | ||||
| 		err_setstr(TypeError, "__nonzero__ should return an int"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	outcome = getintvalue(res); | ||||
| 	DECREF(res); | ||||
| 	if (outcome < 0) { | ||||
| 		err_setstr(ValueError, "__nonzero__ should return >= 0"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return outcome > 0; | ||||
| } | ||||
| 
 | ||||
| UNARY(instance_invert, "__invert__") | ||||
| BINARY(instance_lshift, "__lshift__") | ||||
| BINARY(instance_rshift, "__rshift__") | ||||
| BINARY(instance_and, "__and__") | ||||
| BINARY(instance_xor, "__xor__") | ||||
| BINARY(instance_or, "__or__") | ||||
| 
 | ||||
| static number_methods instance_as_number = { | ||||
| 	instance_add,		/*nb_add*/ | ||||
| 	instance_sub,		/*nb_subtract*/ | ||||
| 	instance_mul,		/*nb_multiply*/ | ||||
| 	instance_div,		/*nb_divide*/ | ||||
| 	instance_mod,		/*nb_remainder*/ | ||||
| 	instance_divmod,	/*nb_divmod*/ | ||||
| 	instance_pow,		/*nb_power*/ | ||||
| 	instance_neg,		/*nb_negative*/ | ||||
| 	instance_pos,		/*nb_positive*/ | ||||
| 	instance_abs,		/*nb_absolute*/ | ||||
| 	instance_nonzero,	/*nb_nonzero*/ | ||||
| 	instance_invert,	/*nb_invert*/ | ||||
| 	instance_lshift,	/*nb_lshift*/ | ||||
| 	instance_rshift,	/*nb_rshift*/ | ||||
| 	instance_and,		/*nb_and*/ | ||||
| 	instance_xor,		/*nb_xor*/ | ||||
| 	instance_or,		/*nb_or*/ | ||||
| }; | ||||
| 
 | ||||
| typeobject Instancetype = { | ||||
| 	OB_HEAD_INIT(&Typetype) | ||||
| 	0, | ||||
|  | @ -253,16 +680,76 @@ typeobject Instancetype = { | |||
| 	sizeof(instanceobject), | ||||
| 	0, | ||||
| 	instance_dealloc,	/*tp_dealloc*/ | ||||
| 	0,			/*tp_print*/ | ||||
| 	instance_print,		/*tp_print*/ | ||||
| 	instance_getattr,	/*tp_getattr*/ | ||||
| 	instance_setattr,	/*tp_setattr*/ | ||||
| 	0,			/*tp_compare*/ | ||||
| 	0,			/*tp_repr*/ | ||||
| 	0,			/*tp_as_number*/ | ||||
| 	0,			/*tp_as_sequence*/ | ||||
| 	0,			/*tp_as_mapping*/ | ||||
| 	instance_compare,	/*tp_compare*/ | ||||
| 	instance_repr,		/*tp_repr*/ | ||||
| 	&instance_as_number,	/*tp_as_number*/ | ||||
| 	&instance_as_sequence,	/*tp_as_sequence*/ | ||||
| 	&instance_as_mapping,	/*tp_as_mapping*/ | ||||
| }; | ||||
| 
 | ||||
| static int | ||||
| one_coerce(pv, pw) | ||||
| 	object **pv, **pw; | ||||
| { | ||||
| 	object *v = *pv; | ||||
| 	object *w = *pw; | ||||
| 	object *func; | ||||
| 
 | ||||
| 	if (!is_instanceobject(v)) | ||||
| 		return 1; | ||||
| 	func = instance_getattr((instanceobject *)v, "__coerce__"); | ||||
| 	if (func == NULL) { | ||||
| 		err_clear(); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	if (func != NULL) { | ||||
| 		object *res = call_object(func, w); | ||||
| 		int outcome; | ||||
| 		if (res == NULL) | ||||
| 			return -1; | ||||
| 		outcome = getargs(res, "(OO)", &v, &w); | ||||
| 		if (!outcome || v->ob_type != w->ob_type || | ||||
| 			        v->ob_type->tp_as_number == NULL) { | ||||
| 			DECREF(res); | ||||
| 			err_setstr(TypeError, "bad __coerce__ result"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		INCREF(v); | ||||
| 		INCREF(w); | ||||
| 		DECREF(res); | ||||
| 		*pv = v; | ||||
| 		*pw = w; | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int | ||||
| instance_coerce(pv, pw) | ||||
| 	object **pv, **pw; | ||||
| { | ||||
| 	int outcome; | ||||
| 	outcome = one_coerce(pv, pw); | ||||
| 	if (outcome > 0) { | ||||
| 		outcome = one_coerce(pw, pv); | ||||
| 		if (outcome > 0) { | ||||
| 			err_setstr(TypeError, "uncoerceable instance"); | ||||
| 			outcome = -1; | ||||
| 		} | ||||
| 	} | ||||
| 	return outcome; | ||||
| } | ||||
| 
 | ||||
| object * | ||||
| instance_convert(inst, methodname) | ||||
| 	object *inst; | ||||
| 	char *methodname; | ||||
| { | ||||
| 	return generic_unary_op((instanceobject *)inst, methodname); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* And finally, here are instance method objects */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -84,6 +84,24 @@ builtin_chr(self, v) | |||
| 	return newsizedstringobject(s, 1); | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
| builtin_coerce(self, args) | ||||
| 	object *self; | ||||
| 	object *args; | ||||
| { | ||||
| 	object *v, *w; | ||||
| 	object *res; | ||||
| 
 | ||||
| 	if (!getargs(args, "(OO)", &v, &w)) | ||||
| 		return NULL; | ||||
| 	if (coerce(&v, &w) < 0) | ||||
| 		return NULL; | ||||
| 	res = mkvalue("(OO)", v, w); | ||||
| 	DECREF(v); | ||||
| 	DECREF(w); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
| builtin_dir(self, v) | ||||
| 	object *self; | ||||
|  | @ -250,6 +268,9 @@ builtin_float(self, v) | |||
| 		INCREF(v); | ||||
| 		return v; | ||||
| 	} | ||||
| 	else if (is_instanceobject(v)) { | ||||
| 		return instance_convert(v, "__float__"); | ||||
| 	} | ||||
| 	err_setstr(TypeError, "float() argument must be int, long or float"); | ||||
| 	return NULL; | ||||
| } | ||||
|  | @ -359,6 +380,9 @@ builtin_int(self, v) | |||
| 		/* XXX should check for overflow */ | ||||
| 		return newintobject((long)x); | ||||
| 	} | ||||
| 	else if (is_instanceobject(v)) { | ||||
| 		return instance_convert(v, "__int__"); | ||||
| 	} | ||||
| 	err_setstr(TypeError, "int() argument must be int, long or float"); | ||||
| 	return NULL; | ||||
| } | ||||
|  | @ -385,6 +409,9 @@ builtin_len(self, v) | |||
| 		err_setstr(TypeError, "len() of unsized object"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	if (len < 0) | ||||
| 		return NULL; | ||||
| 	else | ||||
| 		return newintobject(len); | ||||
| } | ||||
| 
 | ||||
|  | @ -407,6 +434,9 @@ builtin_long(self, v) | |||
| 		double x = getfloatvalue(v); | ||||
| 		return dnewlongobject(x); | ||||
| 	} | ||||
| 	else if (is_instanceobject(v)) { | ||||
| 		return instance_convert(v, "__long__"); | ||||
| 	} | ||||
| 	err_setstr(TypeError, "long() argument must be int, long or float"); | ||||
| 	return NULL; | ||||
| } | ||||
|  | @ -648,6 +678,7 @@ static struct methodlist builtin_methods[] = { | |||
| 	{"abs",		builtin_abs}, | ||||
| 	{"apply",	builtin_apply}, | ||||
| 	{"chr",		builtin_chr}, | ||||
| 	{"coerce",	builtin_coerce}, | ||||
| 	{"dir",		builtin_dir}, | ||||
| 	{"divmod",	builtin_divmod}, | ||||
| 	{"eval",	builtin_eval}, | ||||
|  | @ -766,6 +797,8 @@ coerce(pv, pw) | |||
| 		INCREF(w); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (is_instanceobject(v) || is_instanceobject(w)) | ||||
| 		return instance_coerce(pv, pw); | ||||
| 	if (v->ob_type->tp_as_number == NULL || | ||||
| 					w->ob_type->tp_as_number == NULL) { | ||||
| 		err_setstr(TypeError, "mixing number and non-number"); | ||||
|  |  | |||
							
								
								
									
										104
									
								
								Python/ceval.c
									
										
									
									
									
								
							
							
						
						
									
										104
									
								
								Python/ceval.c
									
										
									
									
									
								
							|  | @ -36,6 +36,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| #include "bltinmodule.h" | ||||
| #include "traceback.h" | ||||
| 
 | ||||
| /* Turn this on if your compiler chokes on the big switch: */ | ||||
| /* #define CASE_TOO_BIG 1 /**/ | ||||
| 
 | ||||
| #ifndef NDEBUG | ||||
| /* For debugging the interpreter: */ | ||||
| #define LLTRACE  1	/* Low-level trace feature */ | ||||
|  | @ -106,13 +109,13 @@ init_save_thread() | |||
|    dynamically loaded modules needn't be compiled separately for use | ||||
|    with and without threads: */ | ||||
| 
 | ||||
| void * | ||||
| object * | ||||
| save_thread() | ||||
| { | ||||
| #ifdef USE_THREAD | ||||
| 	if (interpreter_lock) { | ||||
| 		void *res; | ||||
| 		res = (void *)current_frame; | ||||
| 		object *res; | ||||
| 		res = (object *)current_frame; | ||||
| 		current_frame = NULL; | ||||
| 		release_lock(interpreter_lock); | ||||
| 		return res; | ||||
|  | @ -124,7 +127,7 @@ save_thread() | |||
| 
 | ||||
| void | ||||
| restore_thread(x) | ||||
| 	void *x; | ||||
| 	object *x; | ||||
| { | ||||
| #ifdef USE_THREAD | ||||
| 	if (interpreter_lock) { | ||||
|  | @ -723,6 +726,10 @@ eval_code(co, globals, locals, arg) | |||
| 				err_setstr(NameError, getstringvalue(w)); | ||||
| 			break; | ||||
| 
 | ||||
| #ifdef CASE_TOO_BIG | ||||
| 		default: switch (opcode) { | ||||
| #endif | ||||
| 		 | ||||
| 		case UNPACK_VARARG: | ||||
| 			if (EMPTY()) { | ||||
| 				err_setstr(TypeError, | ||||
|  | @ -1023,13 +1030,19 @@ eval_code(co, globals, locals, arg) | |||
| 			break; | ||||
| 		 | ||||
| 		case JUMP_IF_FALSE: | ||||
| 			if (!testbool(TOP())) | ||||
| 			err = testbool(TOP()); | ||||
| 			if (err > 0) | ||||
| 				err = 0; | ||||
| 			else if (err == 0) | ||||
| 				JUMPBY(oparg); | ||||
| 			break; | ||||
| 		 | ||||
| 		case JUMP_IF_TRUE: | ||||
| 			if (testbool(TOP())) | ||||
| 			err = testbool(TOP()); | ||||
| 			if (err > 0) { | ||||
| 				err = 0; | ||||
| 				JUMPBY(oparg); | ||||
| 			} | ||||
| 			break; | ||||
| 		 | ||||
| 		case JUMP_ABSOLUTE: | ||||
|  | @ -1093,6 +1106,10 @@ eval_code(co, globals, locals, arg) | |||
| 			why = WHY_EXCEPTION; | ||||
| 			break; | ||||
| 
 | ||||
| #ifdef CASE_TOO_BIG | ||||
| 		} | ||||
| #endif | ||||
| 
 | ||||
| 		} /* switch */ | ||||
| 
 | ||||
| 	    on_error: | ||||
|  | @ -1388,22 +1405,27 @@ flushline() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Test a value used as condition, e.g., in a for or if statement */ | ||||
| /* Test a value used as condition, e.g., in a for or if statement.
 | ||||
|    Return -1 if an error occurred */ | ||||
| 
 | ||||
| static int | ||||
| testbool(v) | ||||
| 	object *v; | ||||
| { | ||||
| 	int res; | ||||
| 	if (v == None) | ||||
| 		return 0; | ||||
| 	if (v->ob_type->tp_as_number != NULL) | ||||
| 		return (*v->ob_type->tp_as_number->nb_nonzero)(v); | ||||
| 	if (v->ob_type->tp_as_sequence != NULL) | ||||
| 		return (*v->ob_type->tp_as_sequence->sq_length)(v) != 0; | ||||
| 	if (v->ob_type->tp_as_mapping != NULL) | ||||
| 		return (*v->ob_type->tp_as_mapping->mp_length)(v) != 0; | ||||
| 	/* All other objects are 'true' */ | ||||
| 	return 1; | ||||
| 		res = 0; | ||||
| 	else if (v->ob_type->tp_as_number != NULL) | ||||
| 		res = (*v->ob_type->tp_as_number->nb_nonzero)(v); | ||||
| 	else if (v->ob_type->tp_as_mapping != NULL) | ||||
| 		res = (*v->ob_type->tp_as_mapping->mp_length)(v); | ||||
| 	else if (v->ob_type->tp_as_sequence != NULL) | ||||
| 		res = (*v->ob_type->tp_as_sequence->sq_length)(v); | ||||
| 	else | ||||
| 		res = 0; | ||||
| 	if (res > 0) | ||||
| 		res = 1; | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
|  | @ -1649,7 +1671,13 @@ not(v) | |||
| 	object *v; | ||||
| { | ||||
| 	int outcome = testbool(v); | ||||
| 	object *w = outcome == 0 ? True : False; | ||||
| 	object *w; | ||||
| 	if (outcome < 0) | ||||
| 		return NULL; | ||||
| 	if (outcome == 0) | ||||
| 		w = True; | ||||
| 	else | ||||
| 		w = False; | ||||
| 	INCREF(w); | ||||
| 	return w; | ||||
| } | ||||
|  | @ -1780,18 +1808,24 @@ apply_subscript(v, w) | |||
| 		err_setstr(TypeError, "unsubscriptable object"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	if (tp->tp_as_sequence != NULL) { | ||||
| 	if (tp->tp_as_mapping != NULL) { | ||||
| 		return (*tp->tp_as_mapping->mp_subscript)(v, w); | ||||
| 	} | ||||
| 	else { | ||||
| 		int i; | ||||
| 		if (!is_intobject(w)) { | ||||
| 			err_setstr(TypeError, "sequence subscript not int"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		i = getintvalue(w); | ||||
| 		if (i < 0) | ||||
| 			i += (*tp->tp_as_sequence->sq_length)(v); | ||||
| 		if (i < 0) { | ||||
| 			int len = (*tp->tp_as_sequence->sq_length)(v); | ||||
| 			if (len < 0) | ||||
| 				return NULL; | ||||
| 			i += len; | ||||
| 		} | ||||
| 		return (*tp->tp_as_sequence->sq_item)(v, i); | ||||
| 	} | ||||
| 	return (*tp->tp_as_mapping->mp_subscript)(v, w); | ||||
| } | ||||
| 
 | ||||
| static object * | ||||
|  | @ -1841,6 +1875,8 @@ apply_slice(u, v, w) /* return u[v:w] */ | |||
| 	} | ||||
| 	ilow = 0; | ||||
| 	isize = ihigh = (*tp->tp_as_sequence->sq_length)(u); | ||||
| 	if (isize < 0) | ||||
| 		return NULL; | ||||
| 	if (slice_index(v, isize, &ilow) != 0) | ||||
| 		return NULL; | ||||
| 	if (slice_index(w, isize, &ihigh) != 0) | ||||
|  | @ -1858,7 +1894,11 @@ assign_subscript(w, key, v) /* w[key] = v */ | |||
| 	sequence_methods *sq; | ||||
| 	mapping_methods *mp; | ||||
| 	int (*func)(); | ||||
| 	if ((sq = tp->tp_as_sequence) != NULL && | ||||
| 	if ((mp = tp->tp_as_mapping) != NULL && | ||||
| 			(func = mp->mp_ass_subscript) != NULL) { | ||||
| 		return (*func)(w, key, v); | ||||
| 	} | ||||
| 	else if ((sq = tp->tp_as_sequence) != NULL && | ||||
| 			(func = sq->sq_ass_item) != NULL) { | ||||
| 		if (!is_intobject(key)) { | ||||
| 			err_setstr(TypeError, | ||||
|  | @ -1867,15 +1907,15 @@ assign_subscript(w, key, v) /* w[key] = v */ | |||
| 		} | ||||
| 		else { | ||||
| 			int i = getintvalue(key); | ||||
| 			if (i < 0) | ||||
| 				i += (*sq->sq_length)(w); | ||||
| 			if (i < 0) { | ||||
| 				int len = (*sq->sq_length)(w); | ||||
| 				if (len < 0) | ||||
| 					return -1; | ||||
| 				i += len; | ||||
| 			} | ||||
| 			return (*func)(w, i, v); | ||||
| 		} | ||||
| 	} | ||||
| 	else if ((mp = tp->tp_as_mapping) != NULL && | ||||
| 			(func = mp->mp_ass_subscript) != NULL) { | ||||
| 		return (*func)(w, key, v); | ||||
| 	} | ||||
| 	else { | ||||
| 		err_setstr(TypeError, | ||||
| 				"can't assign to this subscripted object"); | ||||
|  | @ -1899,6 +1939,8 @@ assign_slice(u, v, w, x) /* u[v:w] = x */ | |||
| 	} | ||||
| 	ilow = 0; | ||||
| 	isize = ihigh = (*sq->sq_length)(u); | ||||
| 	if (isize < 0) | ||||
| 		return -1; | ||||
| 	if (slice_index(v, isize, &ilow) != 0) | ||||
| 		return -1; | ||||
| 	if (slice_index(w, isize, &ihigh) != 0) | ||||
|  | @ -1955,6 +1997,8 @@ cmp_member(v, w) | |||
| 		return -1; | ||||
| 	} | ||||
| 	n = (*sq->sq_length)(w); | ||||
| 	if (n < 0) | ||||
| 		return -1; | ||||
| 	for (i = 0; i < n; i++) { | ||||
| 		x = (*sq->sq_item)(w, i); | ||||
| 		cmp = cmpobject(v, x); | ||||
|  | @ -1977,7 +2021,7 @@ cmp_outcome(op, v, w) | |||
| 	case IS: | ||||
| 	case IS_NOT: | ||||
| 		res = (v == w); | ||||
| 		if (op == IS_NOT) | ||||
| 		if (op == (int) IS_NOT) | ||||
| 			res = !res; | ||||
| 		break; | ||||
| 	case IN: | ||||
|  | @ -1985,7 +2029,7 @@ cmp_outcome(op, v, w) | |||
| 		res = cmp_member(v, w); | ||||
| 		if (res < 0) | ||||
| 			return NULL; | ||||
| 		if (op == NOT_IN) | ||||
| 		if (op == (int) NOT_IN) | ||||
| 			res = !res; | ||||
| 		break; | ||||
| 	case EXC_MATCH: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum