added moo_process_t.perr and Processor>>primError to capture the last error set by a primitive function

This commit is contained in:
hyunghwan.chung 2017-04-25 15:20:58 +00:00
parent d3c9a33c30
commit 8298bad3e0
5 changed files with 90 additions and 69 deletions

View File

@ -1,4 +1,38 @@
class Apex(nil) 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 method basicAt: index
{ {
| perr |
<primitive: #_basic_at> <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 method basicAt: index put: anObject
{ {
| perr |
<primitive: #_basic_at_put> <primitive: #_basic_at_put>
## TODO: proper error handling
(* perr := thisProcess primError.
if (primitiveError == error(generic)) if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) }
{ elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt:put: }
} else { self primitiveFailed }
else
{
self index: index outOfRange: (self basicSize).
}*)
self index: index outOfRange: (self basicSize).
} }
method(#class) basicAt: index method(#class) basicAt: index
{ {
| perr |
<primitive: #_basic_at> <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 method(#class) basicAt: index put: anObject
{ {
| perr |
<primitive: #_basic_at_put> <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 extend Error
{ {

View File

@ -1,33 +1,21 @@
class(#pointer) Process(Object) 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 method new
{ {
"instantiation is not allowed" "instantiation is not allowed"
^nil. "TODO: raise an exception" ^nil. "TODO: raise an exception or return an error"
} }
method prev method prev { ^self.prev }
{ method next { ^self.next }
^self.prev.
}
method next method next: process { self.next := process }
{ method prev: process { self.prev := process }
^self.next.
}
method next: process method primError { ^self.perr }
{
self.next := process.
}
method prev: process
{
self.prev := process.
}
method resume method resume
{ {

View File

@ -3214,8 +3214,13 @@ if super is variable-nonpointer, no instance variable is allowed.
GET_TOKEN (moo); GET_TOKEN (moo);
/* [NOTE] default value assignment. only a literal is allowed */ /* [NOTE] default value assignment. only a literal is allowed
lit = token_to_literal (moo, 1); * 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; if (!lit) return -1;
/* set the initial value for the variable added above */ /* 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 (__read_byte_array_literal (moo, &lit) <= -1) return -1;
if (rdonly) 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); MOO_OBJ_SET_FLAGS_RDONLY (lit, 1);
} }
break; break;
@ -7071,7 +7076,9 @@ static MOO_INLINE moo_oop_t token_to_literal (moo_t* moo, int rdonly)
} }
#if 0 #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:
case MOO_IOTOK_IDENT_DOTTED: case MOO_IOTOK_IDENT_DOTTED:
#endif #endif

View File

@ -160,6 +160,7 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c)
proc->initial_context = c; proc->initial_context = c;
proc->current_context = c; proc->current_context = c;
proc->sp = MOO_SMOOI_TO_OOP(-1); 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); 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 else
{ {
moo->errnum = MOO_EINVAL;
MOO_DEBUG1 (moo, "Cannot call primitive numbered %zd - invalid number\n", pfnum); 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; goto activate_primitive_method_body;
} }

View File

@ -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_process_t;
typedef struct moo_process_t* moo_oop_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_process_t next;
moo_oop_semaphore_t sem; moo_oop_semaphore_t sem;
moo_oop_t perr; /* last error set by a primitive function */
/* == variable indexed part == */ /* == variable indexed part == */
moo_oop_t slot[1]; /* process stack */ moo_oop_t slot[1]; /* process stack */