added respondsTo: and perform:with:

fixed a bug in Dictionary>>__remove_at:
added gc callback to external modules
This commit is contained in:
hyunghwan.chung
2017-03-19 14:18:37 +00:00
parent 6a2add620b
commit 46ba3bb3f5
12 changed files with 550 additions and 136 deletions

View File

@ -108,6 +108,7 @@
#endif
static void signal_io_semaphore (moo_t* moo, int mask, void* ctx);
static int send_message (moo_t* moo, moo_oop_char_t selector, int to_super, moo_ooi_t nargs);
/* ------------------------------------------------------------------------- */
static MOO_INLINE int vm_startup (moo_t* moo)
@ -1521,6 +1522,7 @@ static moo_pfrc_t pf_basic_at (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_POINTER(rcv))
{
/* the receiver is a special numeric object, not a normal pointer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
@ -1528,11 +1530,13 @@ static moo_pfrc_t pf_basic_at (moo_t* moo, moo_ooi_t nargs)
if (moo_inttooow (moo, pos, &idx) <= 0)
{
/* negative integer or not integer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
if (idx >= MOO_OBJ_GET_SIZE(rcv))
{
/* index out of range */
moo->errnum = MOO_ERANGE;
return MOO_PF_FAILURE;
}
@ -1580,6 +1584,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_POINTER(rcv))
{
/* the receiver is a special numeric object, not a normal pointer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
pos = MOO_STACK_GETARG(moo, nargs, 0);
@ -1588,11 +1593,13 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (moo_inttooow (moo, pos, &idx) <= 0)
{
/* negative integer or not integer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
if (idx >= MOO_OBJ_GET_SIZE(rcv))
{
/* index out of range */
moo->errnum = MOO_ERANGE;
return MOO_PF_FAILURE;
}
@ -1601,6 +1608,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
/* TODO: disallow change of some key kernel objects???? */
/* TODO: is it better to introduct a read-only mark in the object header instead of this class check??? */
/* read-only object */ /* TODO: DEVISE A WAY TO PASS a proper error from the primitive handler to MOO */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
@ -1610,6 +1618,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_SMOOI(val))
{
/* the value is not a character */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
/* TOOD: must I check the range of the value? */
@ -1620,6 +1629,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_CHAR(val))
{
/* the value is not a character */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
((moo_oop_char_t)rcv)->slot[idx] = MOO_OOP_TO_CHAR(val);
@ -1629,6 +1639,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_SMOOI(val))
{
/* the value is not a number */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
@ -1643,6 +1654,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (moo_inttooow (moo, val, &w) <= 0)
{
/* the value is not a number, out of range, or negative */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
((moo_oop_word_t)rcv)->slot[idx] = w;
@ -1712,6 +1724,7 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
default:
/* MOO_OBJ_TYPE_OOP, ... */
MOO_DEBUG1 (moo, "<pf_hash> Cannot hash an object of type %d\n", type);
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
break;
@ -1726,6 +1739,65 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_responds_to (moo_t* moo, moo_ooi_t nargs)
{
moo_oop_t rcv, selector;
moo_oocs_t mthname;
rcv = MOO_STACK_GETRCV(moo, nargs);
selector = MOO_STACK_GETARG(moo, nargs, 0);
if (MOO_CLASSOF(moo,selector) != moo->_symbol)
{
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
mthname.ptr = MOO_OBJ_GET_CHAR_SLOT(selector);
mthname.len = MOO_OBJ_GET_SIZE(selector);
if (find_method (moo, rcv, &mthname, 0))
{
MOO_STACK_SETRET (moo, nargs, moo->_true);
}
else
{
MOO_STACK_SETRET (moo, nargs, moo->_false);
}
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_perform (moo_t* moo, moo_ooi_t nargs)
{
moo_oop_t /*rcv,*/ selector;
moo_oow_t ssp, esp, i;
/*rcv = MOO_STACK_GETRCV(moo, nargs);*/
selector = MOO_STACK_GETARG(moo, nargs, 0);
if (MOO_CLASSOF(moo,selector) != moo->_symbol)
{
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
/* remove the selector from the stack */
ssp = MOO_STACK_GETARGSP (moo, nargs, 0);
esp = MOO_STACK_GETARGSP (moo, nargs, nargs - 1);
for (i = ssp; i < esp;)
{
moo_oop_t t;
t = MOO_STACK_GET (moo, i);
i++;
MOO_STACK_SET(moo, i, t);
}
MOO_STACK_POP (moo);
/* emulate message sending */
if (send_message (moo, (moo_oop_char_t)selector, 0, nargs - 1) <= -1) return MOO_PF_HARD_FAILURE;
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_exceptionize_error (moo_t* moo, moo_ooi_t nargs)
{
moo_oop_t rcv;
@ -2719,12 +2791,15 @@ static pf_t pftab[] =
{ 0, 0, pf_hash, "_hash" },
{ 1, 1, pf_responds_to, "_responds_to" },
{ 1, MAX_NARGS, pf_perform, "_perform" },
{ 1, 1, pf_exceptionize_error, "_exceptionize_error" },
{ 1, 1, pf_context_goto, "_context_goto" },
{ 0, MAX_NARGS, pf_block_value, "_block_value" },
{ 0, MAX_NARGS, pf_block_new_process, "_block_new_process" },
{ 0, 0, pf_process_resume, "_process_resume" },
{ 0, 0, pf_process_terminate, "_process_terminate" },
{ 0, 0, pf_process_yield, "_process_yield" },
@ -3043,7 +3118,7 @@ static int send_message (moo_t* moo, moo_oop_char_t selector, int to_super, moo_
receiver = MOO_STACK_GET(moo, moo->sp - nargs);
mthname.ptr = selector->slot;
mthname.ptr = MOO_OBJ_GET_CHAR_SLOT(selector);
mthname.len = MOO_OBJ_GET_SIZE(selector);
method = find_method (moo, receiver, &mthname, to_super);
if (!method)