refreshed whileTrue: and whileFalse:
This commit is contained in:
		| @ -22,6 +22,11 @@ | ||||
| 		^self.ip | ||||
| 	} | ||||
|  | ||||
| 	#method pcplus1 | ||||
| 	{ | ||||
| 		^self.ip + 1 | ||||
| 	} | ||||
|  | ||||
| 	#method pc: anInteger | ||||
| 	{ | ||||
| 		self.ip := anInteger. | ||||
| @ -107,24 +112,31 @@ | ||||
| 		<primitive: #_block_value> | ||||
| 		self primitiveFailed. | ||||
| 	} | ||||
|  | ||||
| 	#method value: a  | ||||
| 	{ | ||||
| 		<primitive: #_block_value> | ||||
| 		self primitiveFailed. | ||||
| 	} | ||||
|  | ||||
| 	#method value: a value: b | ||||
| 	{ | ||||
| 		<primitive: #_block_value> | ||||
| 		self primitiveFailed. | ||||
| 	} | ||||
|  | ||||
| 	#method value: a value: b value: c | ||||
| 	{ | ||||
| 		<primitive: #_block_value> | ||||
| 		self primitiveFailed. | ||||
| 	} | ||||
| 	#method value: a value: b value: c value: d | ||||
| 	{ | ||||
| 		<primitive: #_block_value> | ||||
| 		self primitiveFailed. | ||||
| 	} | ||||
| 	#method value: a value: b value: c value: d value: e | ||||
| 	{ | ||||
| 		<primitive: #_block_value> | ||||
| 		self primitiveFailed. | ||||
| 	} | ||||
|  | ||||
| 	#method ifTrue: aBlock | ||||
| 	{ | ||||
| @ -143,88 +155,128 @@ | ||||
|  | ||||
| 	#method whileTrue: aBlock | ||||
| 	{ | ||||
| ## http://stackoverflow.com/questions/2500483/is-there-a-way-in-a-message-only-language-to-define-a-whiletrue-message-without | ||||
| 		## -------------------------------------------------- | ||||
| 		## Naive implementation | ||||
| 		## -------------------------------------------------- | ||||
| 		## (self value) ifFalse: [^nil]. | ||||
| 		## aBlock value.  | ||||
| 		## self whileTrue: aBlock. | ||||
| 		## -------------------------------------------------- | ||||
|  | ||||
| ## ---------------------------------------------------------------------------- | ||||
| 		## -------------------------------------------------- | ||||
| 		## If VM is built without STIX_USE_PROCSTK | ||||
| 		## -------------------------------------------------- | ||||
| 		## | pc sp | | ||||
| 		## sp := thisContext sp. | ||||
| 		## pc := thisContext pcplus1. | ||||
| 		## self value ifFalse: [ ^nil "^self" ]. | ||||
| 		## aBlock value. | ||||
| 		## thisContext pc: pc sp: sp. | ||||
| 		## -------------------------------------------------- | ||||
|  | ||||
| ##		^(self value) ifTrue: [aBlock value. self whileTrue: aBlock]. | ||||
|  | ||||
| ## ---------------------------------------------------------------------------- | ||||
|  | ||||
| 		## less block context before whileTrue: is recursively sent. | ||||
| 		## whileTrue: is sent in a method context. | ||||
| 		(self value) ifFalse: [^nil]. | ||||
| 		aBlock value.  | ||||
| 		self whileTrue: aBlock. | ||||
|  | ||||
| ## ---------------------------------------------------------------------------- | ||||
|  | ||||
| ## ---------------------------------------------------------------------------- | ||||
| "		| pc sp xsp | | ||||
|  | ||||
| 		sp := thisContext sp. | ||||
| 		sp := sp - 1. ## decrement sp by 1 becuase thisContext pushed above affects the sp method | ||||
| 		pc := thisContext pc. | ||||
| 		self value ifFalse: [ ^nil "^self" ]. | ||||
| 		## -------------------------------------------------- | ||||
| 		## If VM is built with STIX_USE_PROCSTK | ||||
| 		## -------------------------------------------------- | ||||
| 		| pc | | ||||
| 		pc := thisContext pcplus1. | ||||
| 		(self value) ifFalse: [ ^nil "^self" ]. | ||||
| 		aBlock value. | ||||
| 		##thisContext pc: pc - 3 sp: sp. | ||||
| 		##thisContext pc: pc + 2 sp: sp.    | ||||
| 		thisContext pc: pc + 1 sp: sp.    | ||||
| 		## this +2 or - 3 above is dependent on the byte code instruction size used for 'store'   | ||||
| 		## +2 to skip STORE_INTO_TEMP(pc) and POP_STACKTOP. | ||||
| 		## TODO: make it independent of the byte code size  | ||||
| " | ||||
| ## ---------------------------------------------------------------------------- | ||||
|  | ||||
| ##        #<label>: | ||||
| ##		thisContext pc: #<label> sp: sp. | ||||
| ## | ||||
| ##		| pc | | ||||
| ##		pc := thisContext pc. | ||||
| ##		^self value ifTrue: [aBlock value. thisContext pc: pc] | ||||
|  | ||||
| ## ---------------------------------------------------------------------------- | ||||
|  | ||||
| ##		self value ifTrue: [ aBlock value. thisContext restart. ]. | ||||
| 		thisContext pc: pc. | ||||
| 		## -------------------------------------------------- | ||||
| 	} | ||||
|  | ||||
| 	#method whileTrue | ||||
| 	{ | ||||
| 		(self value) ifFalse: [^nil]. | ||||
| 		self whileTrue. | ||||
| 		## (self value) ifFalse: [^nil]. | ||||
| 		## self whileTrue. | ||||
|  | ||||
| 		## -------------------------------------------------- | ||||
| 		## If VM is built with STIX_USE_PROCSTK | ||||
| 		## -------------------------------------------------- | ||||
| 		| pc | | ||||
| 		pc := thisContext pcplus1. | ||||
| 		(self value) ifFalse: [ ^nil "^self" ]. | ||||
| 		thisContext pc: pc. | ||||
| 		## -------------------------------------------------- | ||||
| 	} | ||||
|  | ||||
| 	#method whileFalse: aBlock | ||||
| 	{ | ||||
| 		(self value) ifTrue: [^nil]. | ||||
| 		aBlock value.  | ||||
| 		self whileFalse: aBlock. | ||||
| 		## -------------------------------------------------- | ||||
| 		## Naive implementation | ||||
| 		## -------------------------------------------------- | ||||
| 		## (self value) ifTrue: [^nil]. | ||||
| 		## aBlock value.  | ||||
| 		## self whileFalse: aBlock. | ||||
| 		## -------------------------------------------------- | ||||
|  | ||||
| 		## -------------------------------------------------- | ||||
| 		## If VM is built without STIX_USE_PROCSTK | ||||
| 		## -------------------------------------------------- | ||||
| 		## | pc sp | | ||||
| 		## sp := thisContext sp. | ||||
| 		## pc := thisContext pcplus1. | ||||
| 		## self value ifTrue: [ ^nil "^self" ]. | ||||
| 		## aBlock value. | ||||
| 		## thisContext pc: pc sp: sp. | ||||
| 		## -------------------------------------------------- | ||||
|  | ||||
| 		## -------------------------------------------------- | ||||
| 		## If VM is built with STIX_USE_PROCSTK | ||||
| 		## -------------------------------------------------- | ||||
| 		##  The assignment to 'pc' uses the POP_INTO_TEMPVAR_1. | ||||
| 		##  It pops a value off the stack top, stores it to the second | ||||
| 		##  temporary variable(aBlock is the first temporary variable). | ||||
| 		##  It is a single byte instruction. 'pc' returned by  | ||||
| 		##  'thisContext pcplus1'' should point to the instruction after | ||||
| 		##  the POP_INTO_TEMPVAR_0 instruction. | ||||
| 		## | ||||
| 		##  It would need the increment of 2 if the pair of  | ||||
| 		##  STORE_INTO_TEMPVAR_1 and POP_STACKTOP were used.  | ||||
| 		##  This implementation is subject to the instructions chosen | ||||
| 		##  by the compiler. | ||||
| 		## | ||||
| 		| pc | | ||||
| 		pc := thisContext pcplus1. | ||||
| 		(self value) ifTrue: [ ^nil "^self" ]. | ||||
| 		aBlock value. | ||||
| 		thisContext pc: pc. | ||||
| 		## -------------------------------------------------- | ||||
| 	} | ||||
|  | ||||
| 	#method whileFalse | ||||
| 	{ | ||||
| 		(self value) ifTrue: [^nil]. | ||||
| 		self whileFalse. | ||||
| 		## (self value) ifTrue: [^nil]. | ||||
| 		## self whileFalse. | ||||
|  | ||||
| 		## -------------------------------------------------- | ||||
| 		## If VM is built with STIX_USE_PROCSTK | ||||
| 		## -------------------------------------------------- | ||||
| 		| pc | | ||||
| 		pc := thisContext pcplus1. | ||||
| 		(self value) ifTrue: [ ^nil "^self" ]. | ||||
| 		thisContext pc: pc. | ||||
| 		## -------------------------------------------------- | ||||
| 	} | ||||
|  | ||||
| 	#method pc | ||||
| 	{ | ||||
| 		^ip | ||||
| 		^self.ip | ||||
| 	} | ||||
|  | ||||
| 	#method pc: anInteger | ||||
| 	{ | ||||
| 		ip := anInteger. | ||||
| 		self.ip := anInteger. | ||||
| 	} | ||||
| 	 | ||||
| 	#method sp | ||||
| 	{ | ||||
| 		^sp | ||||
| 		^self.sp | ||||
| 	} | ||||
|  | ||||
| 	#method sp: anInteger | ||||
| 	{ | ||||
| 		sp := anInteger. | ||||
| 		self.sp := anInteger. | ||||
| 	} | ||||
|  | ||||
| 	#method restart | ||||
| @ -255,7 +307,6 @@ thisContext isExceptionHandlerContext dump. | ||||
| 		^self value. | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	#method ensure: aBlock | ||||
| 	{ | ||||
| 		"## | ||||
|  | ||||
| @ -26,14 +26,13 @@ | ||||
|  | ||||
| #include "stix-prv.h" | ||||
|  | ||||
| #define TOKEN_NAME_ALIGN     256 | ||||
| #define CLASS_BUFFER_ALIGN   8 /* 256 */ /*TODO: change 8 to 256 */ | ||||
| #define LITERAL_BUFFER_ALIGN 8 /* 256 */ | ||||
| #define CODE_BUFFER_ALIGN    8 /* 256 */ | ||||
| #define BALIT_BUFFER_ALIGN   8 /* 256 */ | ||||
| #define ARLIT_BUFFER_ALIGN   8 /* 256 */ | ||||
| #define BLK_TMPRCNT_BUFFER_ALIGN 8 | ||||
| #define POOLDIC_OOP_BUFFER_ALIGN 8 | ||||
| #define CLASS_BUFFER_ALIGN       64 | ||||
| #define LITERAL_BUFFER_ALIGN     64 | ||||
| #define CODE_BUFFER_ALIGN        64 | ||||
| #define BALIT_BUFFER_ALIGN       64 | ||||
| #define ARLIT_BUFFER_ALIGN       64 | ||||
| #define BLK_TMPRCNT_BUFFER_ALIGN 32 | ||||
| #define POOLDIC_OOP_BUFFER_ALIGN 32 | ||||
|  | ||||
| /* initial method dictionary size */ | ||||
| #define INSTANCE_METHOD_DICTIONARY_SIZE 256 /* TODO: choose the right size */ | ||||
| @ -643,7 +642,7 @@ static int get_char (stix_t* stix) | ||||
| 	{ | ||||
| 		/* if the previous charater was a newline, | ||||
| 		 * increment the line counter and reset column to 1. | ||||
| 		 * incrementing it line number here instead of | ||||
| 		 * incrementing the line number here instead of | ||||
| 		 * updating inp->lxc causes the line number for | ||||
| 		 * TOK_EOF to be the same line as the lxc newline. */ | ||||
| 		stix->c->curinp->line++; | ||||
|  | ||||
| @ -36,6 +36,10 @@ | ||||
| #	include <sys/time.h> | ||||
| #endif | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #	include <windows.h> | ||||
| #endif | ||||
|  | ||||
| #define PROC_STATE_RUNNING 3 | ||||
| #define PROC_STATE_WAITING 2 | ||||
| #define PROC_STATE_RUNNABLE 1 | ||||
| @ -163,7 +167,27 @@ | ||||
| #endif | ||||
|  | ||||
|  | ||||
| static STIX_INLINE void vm_gettime (stix_ntime_t* now) | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| static void vm_startup (stix_t* stix) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
| 	stix->waitable_timer = CreateWaitableTimer(STIX_NULL, TRUE, STIX_NULL); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void vm_cleanup (stix_t* stix) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
| 	if (stix->waitable_timer) | ||||
| 	{ | ||||
| 		CloseHandle (stix->waitable_timer); | ||||
| 		stix->waitable_timer = STIX_NULL; | ||||
| 	}	 | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static STIX_INLINE void vm_gettime (stix_t* stix, stix_ntime_t* now) | ||||
| { | ||||
| #if defined(HAVE_CLOCK_GETTIME) | ||||
| 	struct timespec ts; | ||||
| @ -180,14 +204,33 @@ static STIX_INLINE void vm_gettime (stix_ntime_t* now) | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static STIX_INLINE void vm_sleep (const stix_ntime_t* dur) | ||||
| static STIX_INLINE void vm_sleep (stix_t* stix, const stix_ntime_t* dur) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
| 	if (stix->waitable_timer) | ||||
| 	{ | ||||
| 		LARGE_INTEGER li; | ||||
| 		li.QuadPart = -STIX_SECNSEC_TO_NSEC(dur->sec, dur->nsec); | ||||
| 		if(SetWaitableTimer(timer, &li, 0, STIX_NULL, STIX_NULL, FALSE) == FALSE) goto normal_sleep; | ||||
| 		WaitForSingleObject(timer, INFINITE); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 	normal_sleep: | ||||
| 		/* fallback to normal Sleep() */ | ||||
| 		Sleep (STIX_SECNSEC_TO_MSEC(dur->sec,dur->nsec)); | ||||
| 	} | ||||
|  | ||||
| #else | ||||
| 	struct timespec ts; | ||||
| 	ts.tv_sec = dur->sec; | ||||
| 	ts.tv_nsec = dur->nsec; | ||||
| 	nanosleep (&ts, STIX_NULL); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c) | ||||
| { | ||||
| 	stix_oop_process_t proc; | ||||
| @ -1782,7 +1825,7 @@ static int prim_processor_add_timed_semaphore (stix_t* stix, stix_ooi_t nargs) | ||||
|  *  | ||||
|  * this code assumes that the monotonic clock returns a small value | ||||
|  * that can fit into a small integer, even after some addtions... */ | ||||
| 	vm_gettime (&now); | ||||
| 	vm_gettime (stix, &now); | ||||
| 	STIX_ADDNTIMESNS (&ft, &now, STIX_OOP_TO_SMOOI(sec), STIX_OOP_TO_SMOOI(nsec)); | ||||
| 	if (ft.sec < 0 || ft.sec > STIX_SMOOI_MAX)  | ||||
| 	{ | ||||
| @ -2961,6 +3004,7 @@ int stix_execute (stix_t* stix) | ||||
|  | ||||
| 	STIX_ASSERT (stix->active_context != STIX_NULL); | ||||
|  | ||||
| 	vm_startup (stix); | ||||
| 	stix->proc_switched = 0; | ||||
|  | ||||
| 	while (1) | ||||
| @ -2968,7 +3012,7 @@ int stix_execute (stix_t* stix) | ||||
| 		if (stix->sem_heap_count > 0) | ||||
| 		{ | ||||
| 			stix_ntime_t ft, now; | ||||
| 			vm_gettime (&now); | ||||
| 			vm_gettime (stix, &now); | ||||
|  | ||||
| 			do | ||||
| 			{ | ||||
| @ -3012,8 +3056,8 @@ int stix_execute (stix_t* stix) | ||||
| 				else if (stix->processor->active == stix->nil_process) | ||||
| 				{ | ||||
| 					STIX_SUBNTIME (&ft, &ft, (stix_ntime_t*)&now); | ||||
| 					vm_sleep (&ft); /* TODO: change this to i/o multiplexer??? */ | ||||
| 					vm_gettime (&now); | ||||
| 					vm_sleep (stix, &ft); /* TODO: change this to i/o multiplexer??? */ | ||||
| 					vm_gettime (stix, &now); | ||||
| 				} | ||||
| 				else  | ||||
| 				{ | ||||
| @ -3983,6 +4027,7 @@ printf ("UNKNOWN BYTE CODE ENCOUNTERED %x\n", (int)bcode); | ||||
|  | ||||
| done: | ||||
|  | ||||
| 	vm_cleanup (stix); | ||||
| #if defined(STIX_PROFILE_EXEC) | ||||
| 	printf ("TOTAL_INST_COUTNER = %lu\n", (unsigned long int)inst_counter); | ||||
| #endif | ||||
|  | ||||
| @ -258,7 +258,7 @@ static int ignite_3 (stix_t* stix) | ||||
| 		{ 20, { 'L','a','r','g','e','N','e','g','a','t','i','v','e','I','n','t','e','g','e','r' } } | ||||
| 	}; | ||||
|  | ||||
| 	static stix_ooch_t str_stix[] = { 'S','t','i','x' }; | ||||
| 	static stix_ooch_t str_system[] = { 'S','y','s','t','e', 'm' }; | ||||
| 	static stix_ooch_t str_processor[] = { 'P', 'r', 'o', 'c', 'e', 's', 's', 'o', 'r' }; | ||||
|  | ||||
| 	stix_oow_t i; | ||||
| @ -280,7 +280,7 @@ static int ignite_3 (stix_t* stix) | ||||
| 	} | ||||
|  | ||||
| 	/* Make the system dictionary available as the global name 'Stix' */ | ||||
| 	sym = stix_makesymbol (stix, str_stix, 4); | ||||
| 	sym = stix_makesymbol (stix, str_system, 6); | ||||
| 	if (!sym) return -1; | ||||
| 	if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->sysdic)) return -1; | ||||
|  | ||||
|  | ||||
| @ -370,7 +370,7 @@ static char* syntax_error_msg[] = | ||||
| 	"literal expected" | ||||
| }; | ||||
|  | ||||
| stix_ooch_t str_stix[] = { 'S', 't', 'i', 'x' }; | ||||
| stix_ooch_t str_system[] = { 'S', 'y', 's', 't', 'e', 'm' }; | ||||
| stix_ooch_t str_my_object[] = { 'M', 'y', 'O', 'b','j','e','c','t' }; | ||||
| stix_ooch_t str_main[] = { 'm', 'a', 'i', 'n' }; | ||||
|  | ||||
| @ -593,8 +593,8 @@ printf ("%p\n", a); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| /*	objname.ptr = str_stix; | ||||
| 	objname.len = 4;*/ | ||||
| /*	objname.ptr = str_system; | ||||
| 	objname.len = 6;*/ | ||||
| 	objname.ptr = str_my_object; | ||||
| 	objname.len = 8; | ||||
| 	mthname.ptr = str_main; | ||||
|  | ||||
| @ -39,7 +39,6 @@ void* stix_allocbytes (stix_t* stix, stix_oow_t size) | ||||
| 	{ | ||||
| 		stix_gc (stix); | ||||
| 		ptr = stix_allocheapmem (stix, stix->curheap, size); | ||||
|  | ||||
| /* TODO: grow heap if ptr is still null. */ | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -169,11 +169,6 @@ | ||||
| #	define STIX_HAVE_INT64_T | ||||
| 	typedef unsigned __int64_t  stix_uint64_t; | ||||
| 	typedef signed __int64_t    stix_int64_t; | ||||
| #elif defined(_WIN64) || defined(_WIN32) | ||||
| #	define STIX_HAVE_UINT64_T | ||||
| #	define STIX_HAVE_INT64_T | ||||
| 	typedef unsigned __int64  stix_uint64_t; | ||||
| 	typedef signed __int64    stix_int64_t; | ||||
| #else | ||||
| 	/* no 64-bit integer */ | ||||
| #endif | ||||
| @ -332,10 +327,13 @@ typedef stix_ucs_t               stix_oocs_t; | ||||
| #define STIX_NSECS_PER_SEC  (STIX_NSECS_PER_USEC * STIX_USECS_PER_MSEC * STIX_MSECS_PER_SEC) | ||||
|  | ||||
| #define STIX_SECNSEC_TO_MSEC(sec,nsec) \ | ||||
|         (((qse_long_t)(sec) * STIX_MSECS_PER_SEC) + ((qse_long_t)(nsec) / STIX_NSECS_PER_MSEC)) | ||||
|         (((stix_intptr_t)(sec) * STIX_MSECS_PER_SEC) + ((stix_intptr_t)(nsec) / STIX_NSECS_PER_MSEC)) | ||||
|  | ||||
| #define STIX_SECNSEC_TO_USEC(sec,nsec) \ | ||||
|         (((qse_long_t)(sec) * STIX_USECS_PER_SEC) + ((qse_long_t)(nsec) / STIX_NSECS_PER_USEC)) | ||||
|         (((stix_intptr_t)(sec) * STIX_USECS_PER_SEC) + ((stix_intptr_t)(nsec) / STIX_NSECS_PER_USEC)) | ||||
|  | ||||
| #define STIX_SECNSEC_TO_NSEC(sec,nsec) \ | ||||
|         (((stix_intptr_t)(sec) * STIX_NSECS_PER_SEC) + (stix_intptr_t)(nsec)) | ||||
|  | ||||
| #define STIX_SEC_TO_MSEC(sec) ((sec) * STIX_MSECS_PER_SEC) | ||||
| #define STIX_MSEC_TO_SEC(sec) ((sec) / STIX_MSECS_PER_SEC) | ||||
| @ -543,7 +541,11 @@ struct stix_cmgr_t | ||||
|  * MACROS THAT CHANGES THE BEHAVIORS OF THE C COMPILER/LINKER | ||||
|  * =========================================================================*/ | ||||
|  | ||||
| #if defined(_WIN32) || (defined(__WATCOMC__) && !defined(__WINDOWS_386__)) | ||||
| #if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) | ||||
| #	define STIX_IMPORT | ||||
| #	define STIX_EXPORT | ||||
| #	define STIX_PRIVATE | ||||
| #elif defined(_WIN32) || (defined(__WATCOMC__) && !defined(__WINDOWS_386__)) | ||||
| #	define STIX_IMPORT __declspec(dllimport) | ||||
| #	define STIX_EXPORT __declspec(dllexport) | ||||
| #	define STIX_PRIVATE  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user