fixed a parameter range check bug in a compiler.
fixed a wrong goto label location for send_message
This commit is contained in:
		| @ -198,10 +198,28 @@ | ||||
|  | ||||
| #class(#liword) LargePositiveInteger(LargeInteger) | ||||
| { | ||||
| 	#method abs | ||||
| 	{ | ||||
| 		^self. | ||||
| 	} | ||||
|  | ||||
| 	#method sign | ||||
| 	{ | ||||
| 		^1. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| #class(#liword) LargeNegativeInteger(LargeInteger) | ||||
| { | ||||
| 	#method abs | ||||
| 	{ | ||||
| 		^self negated. | ||||
| 	} | ||||
| 	 | ||||
| 	#method sign | ||||
| 	{ | ||||
| 		^-1. | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -229,6 +229,19 @@ | ||||
| 		<primitive: #snd_open> | ||||
| 	} | ||||
|  | ||||
| 	#method(#class) a: a b: b c: c | ||||
| 	{ | ||||
| 		c dump. | ||||
| 	} | ||||
|  | ||||
| 	#method(#class) a: a b: b c: c d: d e: e f: f g: g h: h | ||||
| 	{ | ||||
| 		h dump. | ||||
| 	} | ||||
| 	#method(#class) a: a b: b c: c d: d e: e f: f g: g | ||||
| 	{ | ||||
| 		g dump. | ||||
| 	} | ||||
| 	#method(#class) main | ||||
| 	{ | ||||
| " | ||||
| @ -392,6 +405,8 @@ PROCESS TESTING | ||||
| (2r1000000000000000000000000000100000000000000000000000000000000000000000000000 bitAt: 129) dump. | ||||
| (2r1000000000000000000000000000100000000000000000000000000000000000000000000000 bitAt: 16rFFFFFFFFFFFFFFFF1) dump. | ||||
|  | ||||
| 		##self a: 1 b: 2 c: 3 d: 4 e: 5 f: 6 g: 7. | ||||
| 		##self a: 1 b: 2 c: 3. | ||||
| " | ||||
| 		FFI isNil dump. | ||||
| 		FFI notNil dump. | ||||
|  | ||||
| @ -1659,6 +1659,7 @@ static int emit_single_param_instruction (stix_t* stix, int cmd, stix_oow_t para | ||||
| 		case BCODE_PUSH_LITERAL_0: | ||||
| 			if (param_1 < 8) | ||||
| 			{ | ||||
| 				/* low 3 bits to hold the parameter */ | ||||
| 				bc = (stix_oob_t)(cmd & 0xF8) | (stix_oob_t)param_1; | ||||
| 				goto write_short; | ||||
| 			} | ||||
| @ -1678,6 +1679,7 @@ static int emit_single_param_instruction (stix_t* stix, int cmd, stix_oow_t para | ||||
| 		case BCODE_JUMP_IF_FALSE_0: | ||||
| 			if (param_1 < 4) | ||||
| 			{ | ||||
| 				/* low 2 bits to hold the parameter */ | ||||
| 				bc = (stix_oob_t)(cmd & 0xFC) | (stix_oob_t)param_1; | ||||
| 				goto write_short; | ||||
| 			} | ||||
| @ -1730,7 +1732,7 @@ static int emit_double_param_instruction (stix_t* stix, int cmd, stix_oow_t para | ||||
| 		case BCODE_POP_INTO_OBJVAR_0: | ||||
| 		case BCODE_SEND_MESSAGE_0: | ||||
| 		case BCODE_SEND_MESSAGE_TO_SUPER_0: | ||||
| 			if (param_1 < 8 && param_2 < 0xFF) | ||||
| 			if (param_1 < 4 && param_2 < 0xFF) | ||||
| 			{ | ||||
| 				/* low 2 bits of the instruction code is the first parameter */ | ||||
| 				bc = (stix_oob_t)(cmd & 0xFC) | (stix_oob_t)param_1; | ||||
|  | ||||
							
								
								
									
										379
									
								
								stix/lib/exec.c
									
									
									
									
									
								
							
							
						
						
									
										379
									
								
								stix/lib/exec.c
									
									
									
									
									
								
							| @ -2034,6 +2034,195 @@ done: | ||||
| 	return handler; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| static int send_message (stix_t* stix, stix_oop_char_t selector, int to_super, stix_ooi_t nargs) | ||||
| { | ||||
| 	stix_oocs_t mthname; | ||||
| 	stix_oop_t receiver; | ||||
| 	stix_oop_method_t method; | ||||
| 	stix_ooi_t preamble, preamble_code; | ||||
|  | ||||
| 	STIX_ASSERT (STIX_OOP_IS_POINTER(selector)); | ||||
| 	STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(selector) == STIX_OBJ_TYPE_CHAR); | ||||
| 	STIX_ASSERT (STIX_CLASSOF(stix, selector) == stix->_symbol); | ||||
|  | ||||
| 	receiver = ACTIVE_STACK_GET(stix, stix->sp - nargs); | ||||
| #if defined(STIX_DEBUG_EXEC) | ||||
| printf (" RECEIVER = "); | ||||
| print_object(stix, receiver); | ||||
| printf ("\n"); | ||||
| #endif | ||||
|  | ||||
| 	mthname.ptr = selector->slot; | ||||
| 	mthname.len = STIX_OBJ_GET_SIZE(selector); | ||||
| 	method = find_method (stix, receiver, &mthname, to_super); | ||||
| 	if (!method)  | ||||
| 	{ | ||||
| /* TODO: implement doesNotUnderstand: XXXXX  instead of returning -1. */ | ||||
| stix_oop_t c; | ||||
|  | ||||
| c = STIX_CLASSOF(stix,receiver); | ||||
| printf ("ERROR [NOT IMPLEMENTED YET] - receiver ["); | ||||
| print_object (stix, receiver); | ||||
| printf ("] class "); | ||||
| print_object (stix, c); | ||||
| printf (" doesNotUnderstand: ["); | ||||
| print_oocs (&mthname); | ||||
| printf ("]\n"); | ||||
|  | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	STIX_ASSERT (STIX_OOP_TO_SMOOI(method->tmpr_nargs) == nargs); | ||||
|  | ||||
| 	preamble = STIX_OOP_TO_SMOOI(method->preamble); | ||||
| 	preamble_code = STIX_METHOD_GET_PREAMBLE_CODE(preamble); | ||||
| 	switch (preamble_code) | ||||
| 	{ | ||||
| 		case STIX_METHOD_PREAMBLE_RETURN_RECEIVER: | ||||
| 			DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_RECEIVER"); | ||||
| 			ACTIVE_STACK_POPS (stix, nargs); /* pop arguments only*/ | ||||
| 			break; | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_RETURN_NIL: | ||||
| 			DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_NIL"); | ||||
| 			ACTIVE_STACK_POPS (stix, nargs); | ||||
| 			ACTIVE_STACK_SETTOP (stix, stix->_nil); | ||||
| 			break; | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_RETURN_TRUE: | ||||
| 			DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_TRUE"); | ||||
| 			ACTIVE_STACK_POPS (stix, nargs); | ||||
| 			ACTIVE_STACK_SETTOP (stix, stix->_true); | ||||
| 			break; | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_RETURN_FALSE: | ||||
| 			DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_FALSE"); | ||||
| 			ACTIVE_STACK_POPS (stix, nargs); | ||||
| 			ACTIVE_STACK_SETTOP (stix, stix->_false); | ||||
| 			break; | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_RETURN_INDEX: | ||||
| 			DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
| 			ACTIVE_STACK_POPS (stix, nargs); | ||||
| 			ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(STIX_METHOD_GET_PREAMBLE_INDEX(preamble))); | ||||
| 			break; | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_RETURN_NEGINDEX: | ||||
| 			DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_NEGINDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
| 			ACTIVE_STACK_POPS (stix, nargs); | ||||
| 			ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(-STIX_METHOD_GET_PREAMBLE_INDEX(preamble))); | ||||
| 			break; | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_RETURN_INSTVAR: | ||||
| 		{ | ||||
| 			stix_oop_oop_t rcv; | ||||
|  | ||||
| 			ACTIVE_STACK_POPS (stix, nargs); /* pop arguments only */ | ||||
|  | ||||
| 			DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INSTVAR %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
|  | ||||
| 			/* replace the receiver by an instance variable of the receiver */ | ||||
| 			rcv = (stix_oop_oop_t)ACTIVE_STACK_GETTOP(stix); | ||||
| 			STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(rcv) == STIX_OBJ_TYPE_OOP); | ||||
| 			STIX_ASSERT (STIX_OBJ_GET_SIZE(rcv) > STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
|  | ||||
| 			if (rcv == (stix_oop_oop_t)stix->active_context) | ||||
| 			{ | ||||
| 				/* the active context object doesn't keep | ||||
| 				 * the most up-to-date information in the  | ||||
| 				 * 'ip' and 'sp' field. commit these fields | ||||
| 				 * when the object to be accessed is  | ||||
| 				 * the active context. this manual commit | ||||
| 				 * is required because this premable handling | ||||
| 				 * skips activation of a new method context | ||||
| 				 * that would commit these fields.  | ||||
| 				 */ | ||||
| 				STORE_ACTIVE_IP (stix); | ||||
| 				STORE_ACTIVE_SP (stix); | ||||
| 			} | ||||
|  | ||||
| 			/* this accesses the instance variable of the receiver */ | ||||
| 			ACTIVE_STACK_SET (stix, stix->sp, rcv->slot[STIX_METHOD_GET_PREAMBLE_INDEX(preamble)]); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_PRIMITIVE: | ||||
| 		{ | ||||
| 			stix_ooi_t prim_no; | ||||
|  | ||||
| 			prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble); | ||||
| 			DBGOUT_EXEC_1 ("METHOD_PREAMBLE_PRIMITIVE %d", (int)prim_no); | ||||
|  | ||||
| 			if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&  | ||||
| 			    (primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == nargs)) | ||||
| 			{ | ||||
| 				int n; | ||||
|  | ||||
| 				stix_pushtmp (stix, (stix_oop_t*)&method); | ||||
| 				n = primitives[prim_no].handler (stix, nargs); | ||||
| 				stix_poptmp (stix); | ||||
| 				if (n <= -1) return -1; /* hard primitive failure */ | ||||
| 				if (n >= 1) break; /* primitive ok */ | ||||
| 			} | ||||
|  | ||||
| 			/* soft primitive failure */ | ||||
| 			if (activate_new_method (stix, method) <= -1) return -1; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		case STIX_METHOD_PREAMBLE_NAMED_PRIMITIVE: | ||||
| 		{ | ||||
| 			stix_ooi_t prim_name_index; | ||||
| 			stix_oop_t name; | ||||
| 			stix_prim_impl_t handler; | ||||
| 			register stix_oow_t w; | ||||
|  | ||||
| 			prim_name_index = STIX_METHOD_GET_PREAMBLE_INDEX(preamble); | ||||
| 			DBGOUT_EXEC_1 ("METHOD_PREAMBLE_NAMED_PRIMITIVE %d", (int)prim_name_index); | ||||
|  | ||||
| 			name = method->slot[prim_name_index]; | ||||
|  | ||||
| 			STIX_ASSERT (STIX_ISTYPEOF(stix,name,STIX_OBJ_TYPE_CHAR)); | ||||
| 			STIX_ASSERT (STIX_OBJ_GET_FLAGS_EXTRA(name)); | ||||
| 			STIX_ASSERT (STIX_CLASSOF(stix,name) == stix->_symbol); | ||||
|  | ||||
| 			/* merge two SmallIntegers to get a full pointer */ | ||||
| 			w = (stix_oow_t)STIX_OOP_TO_SMOOI(method->preamble_data[0]) << (STIX_OOW_BITS / 2) |  | ||||
| 					(stix_oow_t)STIX_OOP_TO_SMOOI(method->preamble_data[1]); | ||||
| 			handler = (stix_prim_impl_t)w; | ||||
| 			if (!handler) handler = query_prim_module (stix, ((stix_oop_char_t)name)->slot, STIX_OBJ_GET_SIZE(name)); | ||||
|  | ||||
| 			if (handler) | ||||
| 			{ | ||||
| 				int n; | ||||
|  | ||||
| 				/* split a pointer to two OOP fields as SmallIntegers for storing. */ | ||||
| 				method->preamble_data[0] = STIX_SMOOI_TO_OOP((stix_oow_t)handler >> (STIX_OOW_BITS / 2)); | ||||
| 				method->preamble_data[1] = STIX_SMOOI_TO_OOP((stix_oow_t)handler & STIX_LBMASK(stix_oow_t, STIX_OOW_BITS / 2)); | ||||
|  | ||||
| 				stix_pushtmp (stix, (stix_oop_t*)&method); | ||||
| 				n = handler (stix, nargs); | ||||
| 				stix_poptmp (stix); | ||||
| 				if (n <= -1) return -1; /* hard primitive failure */ | ||||
| 				if (n >= 1) break; /* primitive ok*/ | ||||
| 			} | ||||
|  | ||||
| 			/* soft primitive failure or handler not found*/ | ||||
| 			if (activate_new_method (stix, method) <= -1) return -1; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		default: | ||||
| 			STIX_ASSERT (preamble_code == STIX_METHOD_PREAMBLE_NONE); | ||||
| 			if (activate_new_method (stix, method) <= -1) return -1; | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| int stix_execute (stix_t* stix) | ||||
| @ -2501,6 +2690,8 @@ printf ("\n"); | ||||
| 			/* -------------------------------------------------------- */ | ||||
| 			case BCODE_SEND_MESSAGE_X: | ||||
| 			case BCODE_SEND_MESSAGE_TO_SUPER_X: | ||||
| 				/* b1 -> number of arguments  | ||||
| 				 * b2 -> selector index stored in the literal frame */ | ||||
| 				FETCH_PARAM_CODE_TO (stix, b1); | ||||
| 				FETCH_PARAM_CODE_TO (stix, b2); | ||||
| 				goto handle_send_message; | ||||
| @ -2514,205 +2705,21 @@ printf ("\n"); | ||||
| 			case BCODE_SEND_MESSAGE_TO_SUPER_2: | ||||
| 			case BCODE_SEND_MESSAGE_TO_SUPER_3: | ||||
| 			{ | ||||
| 				/* b1 -> number of arguments  | ||||
| 				 * b2 -> index to the selector stored in the literal frame | ||||
| 				 */ | ||||
| 				stix_oocs_t mthname; | ||||
| 				stix_oop_t newrcv; | ||||
| 				stix_oop_method_t newmth; | ||||
| 				stix_oop_char_t selector; | ||||
| 				stix_ooi_t preamble, preamble_code; | ||||
|  | ||||
|  | ||||
| 			handle_send_message: | ||||
| 				b1 = bcode & 0x3; /* low 2 bits */ | ||||
| 				FETCH_BYTE_CODE_TO (stix, b2); | ||||
|  | ||||
| 			handle_send_message: | ||||
| 				/* get the selector from the literal frame */ | ||||
| 				selector = (stix_oop_char_t)stix->active_method->slot[b2]; | ||||
|  | ||||
|  | ||||
| #if defined(STIX_DEBUG_EXEC) | ||||
| printf ("SEND_MESSAGE%s TO RECEIVER AT STACKPOS=%d NARGS=%d SELECTOR=", (((bcode >> 2) & 1)? "_TO_SUPER": ""), (int)(stix->sp - b1), (int)b1); | ||||
| print_object (stix, (stix_oop_t)selector); | ||||
| fflush (stdout); | ||||
| #endif | ||||
| 				STIX_ASSERT (STIX_CLASSOF(stix, selector) == stix->_symbol); | ||||
| 				newrcv = ACTIVE_STACK_GET(stix, stix->sp - b1); | ||||
|  | ||||
| #if defined(STIX_DEBUG_EXEC) | ||||
| printf (" RECEIVER = "); | ||||
| print_object(stix, newrcv); | ||||
| printf ("\n"); | ||||
| #endif | ||||
| 				mthname.ptr = selector->slot; | ||||
| 				mthname.len = STIX_OBJ_GET_SIZE(selector); | ||||
| 				newmth = find_method (stix, newrcv, &mthname, ((bcode >> 2) & 1)); | ||||
| 				if (!newmth)  | ||||
| 				{ | ||||
| /* TODO: implement doesNotUnderstand: XXXXX  instead of returning -1. */ | ||||
| stix_oop_t c; | ||||
|  | ||||
| c = STIX_CLASSOF(stix,newrcv); | ||||
|  | ||||
| printf ("ERROR [NOT IMPLEMENTED YET] - receiver ["); | ||||
| print_object (stix, newrcv); | ||||
| printf ("] class "); | ||||
| print_object (stix, c); | ||||
| printf (" doesNotUnderstand: ["); | ||||
| print_oocs (&mthname); | ||||
| printf ("]\n"); | ||||
| 					goto oops; | ||||
| 				} | ||||
|  | ||||
| 				STIX_ASSERT (STIX_OOP_TO_SMOOI(newmth->tmpr_nargs) == b1); | ||||
|  | ||||
| 				preamble = STIX_OOP_TO_SMOOI(newmth->preamble); | ||||
| 				preamble_code = STIX_METHOD_GET_PREAMBLE_CODE(preamble); | ||||
| 				switch (preamble_code) | ||||
| 				{ | ||||
| 					case STIX_METHOD_PREAMBLE_RETURN_RECEIVER: | ||||
| 						DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_RECEIVER"); | ||||
| 						ACTIVE_STACK_POPS (stix, b1); /* pop arguments only*/ | ||||
| 						break; | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_RETURN_NIL: | ||||
| 						DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_NIL"); | ||||
| 						ACTIVE_STACK_POPS (stix, b1); | ||||
| 						ACTIVE_STACK_SETTOP (stix, stix->_nil); | ||||
| 						break; | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_RETURN_TRUE: | ||||
| 						DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_TRUE"); | ||||
| 						ACTIVE_STACK_POPS (stix, b1); | ||||
| 						ACTIVE_STACK_SETTOP (stix, stix->_true); | ||||
| 						break; | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_RETURN_FALSE: | ||||
| 						DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_FALSE"); | ||||
| 						ACTIVE_STACK_POPS (stix, b1); | ||||
| 						ACTIVE_STACK_SETTOP (stix, stix->_false); | ||||
| 						break; | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_RETURN_INDEX: | ||||
| 						DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
| 						ACTIVE_STACK_POPS (stix, b1); | ||||
| 						ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(STIX_METHOD_GET_PREAMBLE_INDEX(preamble))); | ||||
| 						break; | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_RETURN_NEGINDEX: | ||||
| 						DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_NEGINDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
| 						ACTIVE_STACK_POPS (stix, b1); | ||||
| 						ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(-STIX_METHOD_GET_PREAMBLE_INDEX(preamble))); | ||||
| 						break; | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_RETURN_INSTVAR: | ||||
| 					{ | ||||
| 						stix_oop_oop_t rcv; | ||||
|  | ||||
| 						ACTIVE_STACK_POPS (stix, b1); /* pop arguments only */ | ||||
|  | ||||
| 						DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INSTVAR %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
|  | ||||
| 						/* replace the receiver by an instance variable of the receiver */ | ||||
| 						rcv = (stix_oop_oop_t)ACTIVE_STACK_GETTOP(stix); | ||||
| 						STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(rcv) == STIX_OBJ_TYPE_OOP); | ||||
| 						STIX_ASSERT (STIX_OBJ_GET_SIZE(rcv) > STIX_METHOD_GET_PREAMBLE_INDEX(preamble)); | ||||
|  | ||||
| 						if (rcv == (stix_oop_oop_t)stix->active_context) | ||||
| 						{ | ||||
| 							/* the active context object doesn't keep | ||||
| 							 * the most up-to-date information in the  | ||||
| 							 * 'ip' and 'sp' field. commit these fields | ||||
| 							 * when the object to be accessed is  | ||||
| 							 * the active context. this manual commit | ||||
| 							 * is required because this premable handling | ||||
| 							 * skips activation of a new method context | ||||
| 							 * that would commit these fields.  | ||||
| 							 */ | ||||
| 							STORE_ACTIVE_IP (stix); | ||||
| 							STORE_ACTIVE_SP (stix); | ||||
| 						} | ||||
|  | ||||
| 						/* this accesses the instance variable of the receiver */ | ||||
| 						ACTIVE_STACK_SET (stix, stix->sp, rcv->slot[STIX_METHOD_GET_PREAMBLE_INDEX(preamble)]); | ||||
| 						break; | ||||
| 					} | ||||
|  | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_PRIMITIVE: | ||||
| 					{ | ||||
| 						stix_ooi_t prim_no; | ||||
|  | ||||
| 						prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble); | ||||
| 						DBGOUT_EXEC_1 ("METHOD_PREAMBLE_PRIMITIVE %d", (int)prim_no); | ||||
|  | ||||
| 						if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&  | ||||
| 						    (primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == b1)) | ||||
| 						{ | ||||
| 							int n; | ||||
|  | ||||
| 							stix_pushtmp (stix, (stix_oop_t*)&newmth); | ||||
| 							n = primitives[prim_no].handler (stix, b1); | ||||
| 							stix_poptmp (stix); | ||||
| 							if (n <= -1) goto oops; | ||||
| 							if (n >= 1) break; | ||||
| 						} | ||||
|  | ||||
| 						/* primitive handler failed */ | ||||
| 						if (activate_new_method (stix, newmth) <= -1) goto oops; | ||||
| 						break; | ||||
| 					} | ||||
|  | ||||
| 					case STIX_METHOD_PREAMBLE_NAMED_PRIMITIVE: | ||||
| 					{ | ||||
| 						stix_ooi_t prim_name_index; | ||||
| 						stix_oop_t name; | ||||
| 						stix_prim_impl_t handler; | ||||
| 						register stix_oow_t w; | ||||
|  | ||||
| 						prim_name_index = STIX_METHOD_GET_PREAMBLE_INDEX(preamble); | ||||
| 						DBGOUT_EXEC_1 ("METHOD_PREAMBLE_NAMED_PRIMITIVE %d", (int)prim_name_index); | ||||
|  | ||||
| 						name = newmth->slot[prim_name_index]; | ||||
|  | ||||
| 						STIX_ASSERT (STIX_ISTYPEOF(stix,name,STIX_OBJ_TYPE_CHAR)); | ||||
| 						STIX_ASSERT (STIX_OBJ_GET_FLAGS_EXTRA(name)); | ||||
| 						STIX_ASSERT (STIX_CLASSOF(stix,name) == stix->_symbol); | ||||
|  | ||||
| 						/* merge two SmallIntegers to get a full pointer */ | ||||
| 						w = (stix_oow_t)STIX_OOP_TO_SMOOI(newmth->preamble_data[0]) << (STIX_OOW_BITS / 2) |  | ||||
| 						          (stix_oow_t)STIX_OOP_TO_SMOOI(newmth->preamble_data[1]); | ||||
| 						handler = (stix_prim_impl_t)w; | ||||
| 						if (!handler) handler = query_prim_module (stix, ((stix_oop_char_t)name)->slot, STIX_OBJ_GET_SIZE(name)); | ||||
|  | ||||
| 						if (handler) | ||||
| 						{ | ||||
| 							int n; | ||||
|  | ||||
| 							/* split a pointer to two OOP fields as SmallIntegers for storing. */ | ||||
| 							newmth->preamble_data[0] = STIX_SMOOI_TO_OOP((stix_oow_t)handler >> (STIX_OOW_BITS / 2)); | ||||
| 							newmth->preamble_data[1] = STIX_SMOOI_TO_OOP((stix_oow_t)handler & STIX_LBMASK(stix_oow_t, STIX_OOW_BITS / 2)); | ||||
|  | ||||
| 							stix_pushtmp (stix, (stix_oop_t*)&newmth); | ||||
| 							n = handler (stix, b1); | ||||
| 							stix_poptmp (stix); | ||||
| 							if (n <= -1) goto oops; | ||||
| 							if (n >= 1) break; | ||||
| 						} | ||||
| 						 | ||||
|  | ||||
| 						/* primitive handler failed or not found*/ | ||||
| 						if (activate_new_method (stix, newmth) <= -1) goto oops; | ||||
| 						break; | ||||
| 					} | ||||
|  | ||||
| 					default: | ||||
| 						STIX_ASSERT (preamble_code == STIX_METHOD_PREAMBLE_NONE); | ||||
| 						if (activate_new_method (stix, newmth) <= -1) goto oops; | ||||
| 						break; | ||||
| 				} | ||||
|  | ||||
| 				if (send_message (stix, selector, ((bcode >> 2) & 1), b1) <= -1) goto oops; | ||||
| 				break; /* CMD_SEND_MESSAGE */ | ||||
| 			} | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user