started migrating some primitive functions to a separate file
This commit is contained in:
441
moo/lib/exec.c
441
moo/lib/exec.c
@ -1665,403 +1665,6 @@ start_over:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static moo_pfrc_t pf_identical (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, arg, b;
|
||||
|
||||
MOO_ASSERT (moo, nargs == 1);
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
b = (rcv == arg)? moo->_true: moo->_false;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, b);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_not_identical (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, arg, b;
|
||||
|
||||
MOO_ASSERT (moo, nargs == 1);
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
b = (rcv != arg)? moo->_true: moo->_false;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, b);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static int _equal_objects (moo_t* moo, moo_oop_t rcv, moo_oop_t arg)
|
||||
{
|
||||
int rtag;
|
||||
|
||||
if (rcv == arg) return 1; /* identical. so equal */
|
||||
|
||||
rtag = MOO_OOP_GET_TAG(rcv);
|
||||
if (rtag != MOO_OOP_GET_TAG(arg)) return 0;
|
||||
|
||||
switch (rtag)
|
||||
{
|
||||
case MOO_OOP_TAG_SMOOI:
|
||||
return MOO_OOP_TO_SMOOI(rcv) == MOO_OOP_TO_SMOOI(arg)? 1: 0;
|
||||
|
||||
case MOO_OOP_TAG_SMPTR:
|
||||
return MOO_OOP_TO_SMPTR(rcv) == MOO_OOP_TO_SMPTR(arg)? 1: 0;
|
||||
|
||||
case MOO_OOP_TAG_CHAR:
|
||||
return MOO_OOP_TO_CHAR(rcv) == MOO_OOP_TO_CHAR(arg)? 1: 0;
|
||||
|
||||
case MOO_OOP_TAG_ERROR:
|
||||
return MOO_OOP_TO_ERROR(rcv) == MOO_OOP_TO_ERROR(arg)? 1: 0;
|
||||
|
||||
default:
|
||||
{
|
||||
MOO_ASSERT (moo, MOO_OOP_IS_POINTER(rcv));
|
||||
|
||||
if (MOO_OBJ_GET_CLASS(rcv) != MOO_OBJ_GET_CLASS(arg)) return 0; /* different class, not equal */
|
||||
MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TYPE(rcv) == MOO_OBJ_GET_FLAGS_TYPE(arg));
|
||||
|
||||
if (MOO_OBJ_GET_CLASS(rcv) == moo->_class && rcv != arg)
|
||||
{
|
||||
/* a class object are supposed to be unique */
|
||||
return 0;
|
||||
}
|
||||
if (MOO_OBJ_GET_SIZE(rcv) != MOO_OBJ_GET_SIZE(arg)) return 0; /* different size, not equal */
|
||||
|
||||
switch (MOO_OBJ_GET_FLAGS_TYPE(rcv))
|
||||
{
|
||||
case MOO_OBJ_TYPE_BYTE:
|
||||
case MOO_OBJ_TYPE_CHAR:
|
||||
case MOO_OBJ_TYPE_HALFWORD:
|
||||
case MOO_OBJ_TYPE_WORD:
|
||||
return (MOO_MEMCMP (MOO_OBJ_GET_BYTE_SLOT(rcv), MOO_OBJ_GET_BYTE_SLOT(arg), MOO_BYTESOF(moo,rcv)) == 0)? 1: 0;
|
||||
|
||||
default:
|
||||
{
|
||||
if (rcv == moo->_nil) return arg == moo->_nil? 1: 0;
|
||||
if (rcv == moo->_true) return arg == moo->_true? 1: 0;
|
||||
if (rcv == moo->_false) return arg == moo->_false? 1: 0;
|
||||
|
||||
/* MOO_OBJ_TYPE_OOP, ... */
|
||||
MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TYPE(rcv) == MOO_OBJ_TYPE_OOP);
|
||||
|
||||
#if 1
|
||||
moo_seterrbfmt (moo, MOO_ENOIMPL, "no builtin comparison implemented for %O and %O", rcv, arg); /* TODO: better error code */
|
||||
return -1;
|
||||
#else
|
||||
for (i = 0; i < MOO_OBJ_GET_SIZE(rcv); i++)
|
||||
{
|
||||
/* TODO: remove recursion */
|
||||
|
||||
/* NOTE: even if the object implements the equality method,
|
||||
* this primitive method doesn't honor it. */
|
||||
if (!_equal_objects(moo, ((moo_oop_oop_t)rcv)->slot[i], ((moo_oop_oop_t)arg)->slot[i])) return 0;
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_equal (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, arg;
|
||||
int n;
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
n = _equal_objects (moo, rcv, arg);
|
||||
if (n <= -1) return MOO_PF_FAILURE;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, (n? moo->_true: moo->_false));
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_not_equal (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, arg;
|
||||
int n;
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
n = _equal_objects (moo, rcv, arg);
|
||||
if (n <= -1) return MOO_PF_FAILURE;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, (n? moo->_false: moo->_true));
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_class (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv;
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
MOO_STACK_SETRET (moo, nargs, (moo_oop_t)MOO_CLASSOF(moo, rcv));
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static MOO_INLINE moo_pfrc_t pf_basic_new (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_class_t _class;
|
||||
moo_oop_t szoop, obj;
|
||||
moo_oow_t size = 0; /* size of the variable/indexed part */
|
||||
|
||||
_class = (moo_oop_class_t)MOO_STACK_GETRCV(moo, nargs);
|
||||
if (MOO_CLASSOF(moo, _class) != moo->_class)
|
||||
{
|
||||
/* the receiver is not a class object */
|
||||
MOO_DEBUG1 (moo, "<pf_basic_new> Receiver is not a class - %O\n", _class);
|
||||
moo_seterrbfmt (moo, MOO_EMSGRCV, "non-class receiver - %O", _class);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
/* check if #limited is set on the class */
|
||||
if (MOO_CLASS_SELFSPEC_FLAGS(MOO_OOP_TO_SMOOI(_class->selfspec)) & MOO_CLASS_SELFSPEC_FLAG_LIMITED)
|
||||
{
|
||||
MOO_DEBUG1 (moo, "<pf_basic_new> Receiver is #limited - %O\n", _class);
|
||||
moo_seterrbfmt (moo, MOO_EPERM, "limited receiver - %O", _class);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
if (nargs >= 1)
|
||||
{
|
||||
szoop = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
if (moo_inttooow (moo, szoop, &size) <= 0)
|
||||
{
|
||||
/* integer out of range or not integer */
|
||||
MOO_DEBUG1 (moo, "<pf_basic_new> Size out of range or not integer - %O\n", szoop);
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "size out of range or not integer - %O", szoop);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (MOO_OOP_IS_SMOOI(((moo_oop_class_t)_class)->trsize))
|
||||
{
|
||||
obj = moo_instantiatewithtrailer (moo, _class, size, MOO_NULL, MOO_OOP_TO_SMOOI(((moo_oop_class_t)_class)->trsize));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* moo_instantiate() will ignore size if the instance specification
|
||||
* disallows indexed(variable) parts. */
|
||||
/* TODO: should i check the specification before calling
|
||||
* moo_instantiate()? */
|
||||
obj = moo_instantiate (moo, _class, MOO_NULL, size);
|
||||
}
|
||||
if (!obj) return MOO_PF_FAILURE;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, obj);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_shallow_copy (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, obj;
|
||||
|
||||
MOO_ASSERT (moo, nargs == 0);
|
||||
rcv = MOO_STACK_GETRCV (moo, nargs);
|
||||
|
||||
obj = moo_shallowcopy (moo, rcv);
|
||||
if (!obj) return MOO_PF_FAILURE;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, obj);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_basic_size (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
/* return the number of indexable fields */
|
||||
|
||||
moo_oop_t rcv, sz;
|
||||
|
||||
MOO_ASSERT (moo, nargs == 0);
|
||||
|
||||
rcv = MOO_STACK_GETRCV (moo, nargs);
|
||||
|
||||
if (!MOO_OOP_IS_POINTER(rcv))
|
||||
{
|
||||
sz = MOO_SMOOI_TO_OOP(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = moo_oowtoint (moo, MOO_OBJ_GET_SIZE(rcv));
|
||||
if (!sz) return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
MOO_STACK_SETRET(moo, nargs, sz);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_basic_at (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, pos, v;
|
||||
moo_oow_t idx;
|
||||
|
||||
MOO_ASSERT (moo, nargs == 1);
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
if (!MOO_OOP_IS_POINTER(rcv))
|
||||
{
|
||||
/* the receiver is a special numeric object, not a normal pointer */
|
||||
moo_seterrbfmt (moo, MOO_EMSGRCV, "receiver not indexable - %O", rcv);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
pos = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
if (moo_inttooow (moo, pos, &idx) <= 0)
|
||||
{
|
||||
/* negative integer or not integer */
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "invalid position - %O", pos);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
if (idx >= MOO_OBJ_GET_SIZE(rcv))
|
||||
{
|
||||
/* index out of range */
|
||||
moo_seterrbfmt (moo, MOO_ERANGE, "position out of bound - %O", pos);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
switch (MOO_OBJ_GET_FLAGS_TYPE(rcv))
|
||||
{
|
||||
case MOO_OBJ_TYPE_BYTE:
|
||||
v = MOO_SMOOI_TO_OOP(((moo_oop_byte_t)rcv)->slot[idx]);
|
||||
break;
|
||||
|
||||
case MOO_OBJ_TYPE_CHAR:
|
||||
v = MOO_CHAR_TO_OOP(((moo_oop_char_t)rcv)->slot[idx]);
|
||||
break;
|
||||
|
||||
case MOO_OBJ_TYPE_HALFWORD:
|
||||
/* TODO: LargeInteger if the halfword is too large */
|
||||
v = MOO_SMOOI_TO_OOP(((moo_oop_halfword_t)rcv)->slot[idx]);
|
||||
break;
|
||||
|
||||
case MOO_OBJ_TYPE_WORD:
|
||||
v = moo_oowtoint (moo, ((moo_oop_word_t)rcv)->slot[idx]);
|
||||
if (!v) return MOO_PF_FAILURE;
|
||||
break;
|
||||
|
||||
case MOO_OBJ_TYPE_OOP:
|
||||
v = ((moo_oop_oop_t)rcv)->slot[idx];
|
||||
break;
|
||||
|
||||
default:
|
||||
moo_seterrnum (moo, MOO_EINTERN);
|
||||
return MOO_PF_HARD_FAILURE;
|
||||
}
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, v);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, pos, val;
|
||||
moo_oow_t idx;
|
||||
|
||||
MOO_ASSERT (moo, nargs == 2);
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
if (!MOO_OOP_IS_POINTER(rcv))
|
||||
{
|
||||
/* the receiver is a special numeric object, not a normal pointer */
|
||||
moo_seterrbfmt (moo, MOO_EMSGRCV, "receiver not indexable - %O", rcv);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
if (MOO_OBJ_GET_FLAGS_RDONLY(rcv))
|
||||
{
|
||||
/* TODO: better error handling */
|
||||
moo_seterrbfmt (moo, MOO_EPERM, "now allowed to change a read-only object - %O", rcv);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
pos = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
val = MOO_STACK_GETARG(moo, nargs, 1);
|
||||
|
||||
if (moo_inttooow (moo, pos, &idx) <= 0)
|
||||
{
|
||||
/* negative integer or not integer */
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "invalid position - %O", pos);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
if (idx >= MOO_OBJ_GET_SIZE(rcv))
|
||||
{
|
||||
/* index out of range */
|
||||
moo_seterrbfmt (moo, MOO_ERANGE, "position out of bound - %O", pos);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
switch (MOO_OBJ_GET_FLAGS_TYPE(rcv))
|
||||
{
|
||||
case MOO_OBJ_TYPE_BYTE:
|
||||
if (!MOO_OOP_IS_SMOOI(val))
|
||||
{
|
||||
/* the value is not a character */
|
||||
moo_seterrnum (moo, MOO_EINVAL);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
/* TOOD: must I check the range of the value? */
|
||||
((moo_oop_char_t)rcv)->slot[idx] = MOO_OOP_TO_SMOOI(val);
|
||||
break;
|
||||
|
||||
case MOO_OBJ_TYPE_CHAR:
|
||||
if (!MOO_OOP_IS_CHAR(val))
|
||||
{
|
||||
/* the value is not a character */
|
||||
moo_seterrnum (moo, MOO_EINVAL);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
((moo_oop_char_t)rcv)->slot[idx] = MOO_OOP_TO_CHAR(val);
|
||||
break;
|
||||
|
||||
case MOO_OBJ_TYPE_HALFWORD:
|
||||
if (!MOO_OOP_IS_SMOOI(val))
|
||||
{
|
||||
/* the value is not a number */
|
||||
moo_seterrnum (moo, MOO_EINVAL);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
/* if the small integer is too large, it will get truncated */
|
||||
((moo_oop_halfword_t)rcv)->slot[idx] = MOO_OOP_TO_SMOOI(val);
|
||||
break;
|
||||
|
||||
case MOO_OBJ_TYPE_WORD:
|
||||
{
|
||||
moo_oow_t w;
|
||||
|
||||
if (moo_inttooow (moo, val, &w) <= 0)
|
||||
{
|
||||
/* the value is not a number, out of range, or negative */
|
||||
moo_seterrnum (moo, MOO_EINVAL);
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
((moo_oop_word_t)rcv)->slot[idx] = w;
|
||||
break;
|
||||
}
|
||||
|
||||
case MOO_OBJ_TYPE_OOP:
|
||||
((moo_oop_oop_t)rcv)->slot[idx] = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
moo_seterrnum (moo, MOO_EINTERN);
|
||||
return MOO_PF_HARD_FAILURE;
|
||||
}
|
||||
|
||||
/* TODO: return receiver or value? */
|
||||
MOO_STACK_SETRET (moo, nargs, val);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_add_to_be_finalized (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
/* TODO: check if it has already been added */
|
||||
@ -2145,25 +1748,6 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_is_kind_of (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, _class;
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
_class = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
if (MOO_CLASSOF(moo, _class) == moo->_class &&
|
||||
moo_iskindof(moo, rcv, (moo_oop_class_t)_class))
|
||||
{
|
||||
MOO_STACK_SETRET (moo, nargs, moo->_true);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOO_STACK_SETRET (moo, nargs, moo->_false);
|
||||
}
|
||||
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_responds_to (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
@ -4322,26 +3906,23 @@ static pf_t pftab[] =
|
||||
{ "_integer_inttostr", { pf_integer_inttostr, 1, 1 } },
|
||||
|
||||
{ "Apex_addToBeFinalized", { pf_add_to_be_finalized, 0, 0 } },
|
||||
{ "Apex_basicAt:", { pf_basic_at, 1, 1 } },
|
||||
{ "Apex_basicAt:put:", { pf_basic_at_put, 2, 2 } },
|
||||
{ "Apex_basicNew", { pf_basic_new, 0, 0 } },
|
||||
{ "Apex_basicNew:", { pf_basic_new, 1, 1 } },
|
||||
{ "Apex_basicSize", { pf_basic_size, 0, 0 } },
|
||||
{ "Apex_basicNew", { pf_basic_new, 0, 0 } },
|
||||
{ "Apex_basicNew:", { pf_basic_new, 1, 1 } },
|
||||
{ "Apex_basicSize", { pf_basic_size, 0, 0 } },
|
||||
{ "Apex_class", { pf_class, 0, 0 } },
|
||||
{ "Apex_basicAt:", { moo_pf_basic_at, 1, 1 } },
|
||||
{ "Apex_basicAt:put:", { moo_pf_basic_at_put, 2, 2 } },
|
||||
{ "Apex_basicNew", { moo_pf_basic_new, 0, 0 } },
|
||||
{ "Apex_basicNew:", { moo_pf_basic_new, 1, 1 } },
|
||||
{ "Apex_basicSize", { moo_pf_basic_size, 0, 0 } },
|
||||
{ "Apex_class", { moo_pf_class, 0, 0 } },
|
||||
{ "Apex_hash", { pf_hash, 0, 0 } },
|
||||
{ "Apex_isKindOf:", { pf_is_kind_of, 1, 1, } },
|
||||
{ "Apex_perform", { pf_perform, 1, MA } },
|
||||
{ "Apex_removeToBeFinalized", { pf_remove_to_be_finalized, 0, 0 } },
|
||||
{ "Apex_respondsTo:", { pf_responds_to, 1, 1 } },
|
||||
{ "Apex_shallowCopy", { pf_shallow_copy, 0, 0 } },
|
||||
{ "Apex_shallowCopy", { moo_pf_shallow_copy, 0, 0 } },
|
||||
|
||||
{ "Apex_==", { pf_identical, 1, 1 } },
|
||||
{ "Apex_~~", { pf_not_identical, 1, 1 } },
|
||||
{ "Apex_=", { pf_equal, 1, 1 } },
|
||||
{ "Apex_~=", { pf_not_equal, 1, 1 } },
|
||||
{ "Apex_==", { moo_pf_identical, 1, 1 } },
|
||||
{ "Apex_~~", { moo_pf_not_identical, 1, 1 } },
|
||||
{ "Apex_=", { moo_pf_equal, 1, 1 } },
|
||||
{ "Apex_~=", { moo_pf_not_equal, 1, 1 } },
|
||||
|
||||
{ "BlockContext_value", { pf_block_value, 0, MA } },
|
||||
{ "BlockContext_newProcess", { pf_block_new_process, 0, MA } },
|
||||
|
Reference in New Issue
Block a user