added moo_process_t.perr and Processor>>primError to capture the last error set by a primitive function
This commit is contained in:
		| @ -1,4 +1,38 @@ | ||||
| class Apex(nil) | ||||
| { | ||||
| } | ||||
|  | ||||
| class Error(Apex) | ||||
| { | ||||
| } | ||||
|  | ||||
| pooldic Error.Code | ||||
| { | ||||
| 	ENOERR     := error(0). | ||||
| 	EGENERIC   := error(1). | ||||
| 	ENOIMPL    := error(2). | ||||
| 	ESYSERR    := error(3). | ||||
| 	EINTERN    := error(4). | ||||
| 	ESYSMEM    := error(5). | ||||
| 	EOOMEM     := error(6). | ||||
| 	EINVAL     := error(7). | ||||
| 	ENOENT     := error(8). | ||||
| 	EPERM      := error(12). | ||||
| 	ERANGE     := error(20). | ||||
| (* add more items... *) | ||||
| } | ||||
|  | ||||
| (*pooldic Error.Code2  | ||||
| { | ||||
| 	>> CAN I SUPPORT this kind of redefnition? as of now, it's not accepted because  | ||||
| 	>> Error.Code2.EGENERIC is not a literal. Should i treate pooldic members as a constant | ||||
| 	>> and treat it as if it's a literal like? then even if the defined value changes, | ||||
| 	>> the definition here won't see the change... what is the best way to tackle this issue? | ||||
|  | ||||
| 	EGENERIC := Error.Code2.EGENERIC. | ||||
| }*) | ||||
|  | ||||
| extend Apex | ||||
| { | ||||
| 	## ------------------------------------------------------- | ||||
| 	## ------------------------------------------------------- | ||||
| @ -126,35 +160,49 @@ class Apex(nil) | ||||
|  | ||||
| 	method basicAt: index | ||||
| 	{ | ||||
| 		| perr | | ||||
| 		 | ||||
| 		<primitive: #_basic_at> | ||||
| 		self index: index outOfRange: (self basicSize). | ||||
|  | ||||
| ## TODO: create a common method that translate a primitive error to some standard exceptions of primitive failure. | ||||
| 		perr := thisProcess primError. | ||||
| 		if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) } | ||||
| 		elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt } | ||||
| 		else { self primitiveFailed } | ||||
| 	} | ||||
|  | ||||
| 	method basicAt: index put: anObject | ||||
| 	{ | ||||
| 		| perr | | ||||
| 		 | ||||
| 		<primitive: #_basic_at_put> | ||||
| ## TODO: proper error handling | ||||
| (* | ||||
| 		if (primitiveError == error(generic)) | ||||
| 		{ | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			self index: index outOfRange: (self basicSize). | ||||
| 		}*) | ||||
| 		self index: index outOfRange: (self basicSize). | ||||
|  | ||||
| 		perr := thisProcess primError. | ||||
| 		if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) } | ||||
| 		elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt:put: } | ||||
| 		else { self primitiveFailed } | ||||
| 	} | ||||
|  | ||||
| 	method(#class) basicAt: index | ||||
| 	{ | ||||
| 		| perr | | ||||
| 		<primitive: #_basic_at> | ||||
| 		self index: index outOfRange: (self basicSize). | ||||
|  | ||||
| 		perr := thisProcess primError. | ||||
| 		if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) } | ||||
| 		elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt:put: } | ||||
| 		else { self primitiveFailed } | ||||
| 	} | ||||
|  | ||||
| 	method(#class) basicAt: index put: anObject | ||||
| 	{ | ||||
| 		| perr | | ||||
| 		<primitive: #_basic_at_put> | ||||
| 		self index: index outOfRange: (self basicSize). | ||||
|  | ||||
| 		perr := thisProcess primError. | ||||
| 		if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) } | ||||
| 		elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt:put: } | ||||
| 		else { self primitiveFailed } | ||||
| 	} | ||||
|  | ||||
| 	(* ------------------------------------------------------------------ | ||||
| @ -489,32 +537,6 @@ class UndefinedObject(Apex) | ||||
| } | ||||
|  | ||||
|  | ||||
| class Error(Apex) | ||||
| { | ||||
| } | ||||
|  | ||||
| pooldic Error.Code | ||||
| { | ||||
| 	EGENERIC   := error(1). | ||||
| 	ENOIMPL    := error(2). | ||||
| 	ESYSERR    := error(3). | ||||
| 	EINTERN    := error(4). | ||||
| 	ESYSMEM    := error(5). | ||||
| 	EOOMEM     := error(6). | ||||
| 	EINVAL     := error(7). | ||||
| 	ENOENT     := error(8). | ||||
| (* add more items... *) | ||||
| } | ||||
|  | ||||
| (*pooldic Error.Code2  | ||||
| { | ||||
| 	>> CAN I SUPPORT this kind of redefnition? as of now, it's not accepted because  | ||||
| 	>> Error.Code2.EGENERIC is not a literal. Should i treate pooldic members as a constant | ||||
| 	>> and treat it as if it's a literal like? then even if the defined value changes, | ||||
| 	>> the definition here won't see the change... what is the best way to tackle this issue? | ||||
|  | ||||
| 	EGENERIC := Error.Code2.EGENERIC. | ||||
| }*) | ||||
|  | ||||
| extend Error | ||||
| { | ||||
|  | ||||
| @ -1,33 +1,21 @@ | ||||
|  | ||||
| class(#pointer) Process(Object) | ||||
| { | ||||
| 	var initial_context, current_context, state, sp, prev, next, sem. | ||||
| 	var initial_context, current_context, state, sp, prev, next, sem, perr. | ||||
|  | ||||
| 	method new | ||||
| 	{ | ||||
| 		"instantiation is not allowed" | ||||
| 		^nil. "TODO: raise an exception" | ||||
| 		^nil. "TODO: raise an exception or return an error" | ||||
| 	} | ||||
|  | ||||
| 	method prev | ||||
| 	{ | ||||
| 		^self.prev. | ||||
| 	} | ||||
| 	method prev { ^self.prev } | ||||
| 	method next { ^self.next } | ||||
|  | ||||
| 	method next | ||||
| 	{ | ||||
| 		^self.next. | ||||
| 	} | ||||
| 	method next: process { self.next := process } | ||||
| 	method prev: process { self.prev := process } | ||||
|  | ||||
| 	method next: process | ||||
| 	{ | ||||
| 		self.next := process. | ||||
| 	} | ||||
|  | ||||
| 	method prev: process | ||||
| 	{ | ||||
| 		self.prev := process. | ||||
| 	} | ||||
| 	method primError { ^self.perr } | ||||
|  | ||||
| 	method resume | ||||
| 	{ | ||||
|  | ||||
| @ -3214,8 +3214,13 @@ if super is variable-nonpointer, no instance variable is allowed. | ||||
|  | ||||
| 				GET_TOKEN (moo); | ||||
|  | ||||
| 				/* [NOTE] default value assignment. only a literal is allowed */ | ||||
| 				lit = token_to_literal (moo, 1); | ||||
| 				/* [NOTE] default value assignment. only a literal is allowed  | ||||
| 				 *    the initial values for instance variables and  | ||||
| 				 *    class instance variables are set to read-only. | ||||
| 				 *    this is likely to change if the actual initial | ||||
| 				 *    value assignment upon instantiation employes | ||||
| 				 *    deep-copying in moo_instantiate() and in the compiler. */ | ||||
| 				lit = token_to_literal (moo, dcl_type != VAR_CLASS); | ||||
| 				if (!lit) return -1; | ||||
|  | ||||
| 				/* set the initial value for the variable added above */ | ||||
| @ -4310,7 +4315,7 @@ static int __read_array_literal (moo_t* moo, int rdonly, moo_oop_t* xlit) | ||||
| 				if (__read_byte_array_literal (moo, &lit) <= -1) return -1; | ||||
| 				if (rdonly) | ||||
| 				{ | ||||
| 					MOO_ASSERT (moo, MOO_OOP_IS_POINTER(lit)); | ||||
| 					MOO_ASSERT (moo, lit && MOO_OOP_IS_POINTER(lit)); | ||||
| 					MOO_OBJ_SET_FLAGS_RDONLY (lit, 1); | ||||
| 				} | ||||
| 				break; | ||||
| @ -7071,7 +7076,9 @@ static MOO_INLINE moo_oop_t token_to_literal (moo_t* moo, int rdonly) | ||||
| 		} | ||||
|  | ||||
| #if 0 | ||||
| /* TODO: if a constant name is specified (constant defined in a class)  */ | ||||
| /* TODO: if a constant name is specified (constant defined in a class) or | ||||
|  *       another variable with the default initialization value | ||||
|  *    class { var x := 20, y := x. } */ | ||||
| 		case MOO_IOTOK_IDENT: | ||||
| 		case MOO_IOTOK_IDENT_DOTTED: | ||||
| #endif | ||||
|  | ||||
| @ -160,6 +160,7 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c) | ||||
| 	proc->initial_context = c; | ||||
| 	proc->current_context = c; | ||||
| 	proc->sp = MOO_SMOOI_TO_OOP(-1); | ||||
| 	proc->perr = MOO_ERROR_TO_OOP(MOO_ENOERR); | ||||
|  | ||||
| 	MOO_ASSERT (moo, (moo_oop_t)c->sender == moo->_nil); | ||||
|  | ||||
| @ -3821,9 +3822,11 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				moo->errnum = MOO_EINVAL; | ||||
| 				MOO_DEBUG1 (moo, "Cannot call primitive numbered %zd - invalid number\n", pfnum); | ||||
| 			} | ||||
|  | ||||
| 			moo->processor->active->perr = MOO_ERROR_TO_OOP(moo->errnum); | ||||
| 			goto activate_primitive_method_body; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -704,7 +704,7 @@ struct moo_context_t | ||||
| }; | ||||
|  | ||||
|  | ||||
| #define MOO_PROCESS_NAMED_INSTVARS 7 | ||||
| #define MOO_PROCESS_NAMED_INSTVARS 8 | ||||
| typedef struct moo_process_t moo_process_t; | ||||
| typedef struct moo_process_t* moo_oop_process_t; | ||||
|  | ||||
| @ -725,6 +725,7 @@ struct moo_process_t | ||||
| 	moo_oop_process_t   next; | ||||
|  | ||||
| 	moo_oop_semaphore_t sem; | ||||
| 	moo_oop_t           perr; /* last error set by a primitive function */ | ||||
|  | ||||
| 	/* == variable indexed part == */ | ||||
| 	moo_oop_t slot[1]; /* process stack */ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user